feat(squad): 增强领域核心模型支持角色来源、自适应步骤与黑板基准假设
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+79
-23
@@ -23,16 +23,27 @@ type WorkspaceMetadata struct {
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// RoleSource 标识角色来源
|
||||
type RoleSource string
|
||||
|
||||
const (
|
||||
RoleSourceStandard RoleSource = "standard" // 预设标准化角色 (organizer, searcher, regulatory...)
|
||||
RoleSourceCustom RoleSource = "custom" // 配置文件声明的业务扩展角色
|
||||
RoleSourceAdHoc RoleSource = "ad_hoc" // 规划器现场生成的特设专员
|
||||
)
|
||||
|
||||
// AgentSpec 声明单个专员角色在小队中的设定
|
||||
type AgentSpec struct {
|
||||
Role string `json:"role"`
|
||||
Name string `json:"name"`
|
||||
Model string `json:"model"`
|
||||
Tools []string `json:"tools"`
|
||||
BashPermission string `json:"bash_permission"` // allow, deny
|
||||
Responsibilities []string `json:"responsibilities"`
|
||||
ForbiddenActions []string `json:"forbidden_actions"`
|
||||
InstructionsFile string `json:"instructions_file,omitempty"`
|
||||
Role string `json:"role"`
|
||||
Name string `json:"name"`
|
||||
Source RoleSource `json:"source,omitempty"`
|
||||
BaseRole string `json:"base_role,omitempty"`
|
||||
Model string `json:"model"`
|
||||
Tools []string `json:"tools"`
|
||||
BashPermission string `json:"bash_permission"` // allow, deny
|
||||
Responsibilities []string `json:"responsibilities"`
|
||||
ForbiddenActions []string `json:"forbidden_actions"`
|
||||
InstructionsFile string `json:"instructions_file,omitempty"`
|
||||
}
|
||||
|
||||
// SquadConfig 激活的智能体小队编制
|
||||
@@ -42,27 +53,40 @@ type SquadConfig struct {
|
||||
Agents []AgentSpec `json:"agents"`
|
||||
}
|
||||
|
||||
// PlanningMode 规划模式
|
||||
type PlanningMode string
|
||||
|
||||
const (
|
||||
PlanModeFixedAdaptive PlanningMode = "fixed_adaptive" // 固定文档:基于基线模板,允许动态微调
|
||||
PlanModeAutonomousAdhoc PlanningMode = "autonomous_adhoc" // 非工作流:全自动动态规划
|
||||
)
|
||||
|
||||
// StepSpec 单个任务步骤规格定义
|
||||
type StepSpec struct {
|
||||
ID string `json:"id"`
|
||||
Role string `json:"role"`
|
||||
Title string `json:"title"`
|
||||
SubWorkspace string `json:"sub_workspace"` // 相对子路径,如 tasks/01_organize
|
||||
Mode string `json:"mode"` // execute, plan, review_plan, replan
|
||||
Parallel bool `json:"parallel"`
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Accept []string `json:"accept,omitempty"`
|
||||
Status string `json:"status"` // pending, running, completed, failed, skipped
|
||||
DurationMs int64 `json:"duration_ms,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Role string `json:"role"`
|
||||
Title string `json:"title"`
|
||||
SubWorkspace string `json:"sub_workspace"` // 相对子路径,如 tasks/01_organize
|
||||
Mode string `json:"mode"` // execute, plan, review_plan, replan
|
||||
Parallel bool `json:"parallel"`
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Accept []string `json:"accept,omitempty"`
|
||||
Status string `json:"status"` // pending, running, completed, failed, skipped
|
||||
DurationMs int64 `json:"duration_ms,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
AllowDynamicAdjustment bool `json:"allow_dynamic_adjustment,omitempty"`
|
||||
BaselineAssumptions []string `json:"baseline_assumptions,omitempty"`
|
||||
}
|
||||
|
||||
// WorkflowPlan 动态任务编排清单
|
||||
type WorkflowPlan struct {
|
||||
WorkflowID string `json:"workflow_id"`
|
||||
Status string `json:"status"` // pending, in_progress, completed, failed
|
||||
CurrentStepIndex int `json:"current_step_index"`
|
||||
Steps []StepSpec `json:"steps"`
|
||||
WorkflowID string `json:"workflow_id"`
|
||||
TaskKey string `json:"task_key,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
PlanningMode PlanningMode `json:"planning_mode,omitempty"`
|
||||
Status string `json:"status"` // pending, in_progress, completed, failed
|
||||
CurrentStepIndex int `json:"current_step_index"`
|
||||
Steps []StepSpec `json:"steps"`
|
||||
}
|
||||
|
||||
// ContextItem 上下文项目元数据
|
||||
@@ -126,15 +150,47 @@ type ImplicationItem struct {
|
||||
Statement string `json:"statement"`
|
||||
}
|
||||
|
||||
// AssumptionItem 黑板基准假设项(医疗器械工程/法规先验推断)
|
||||
type AssumptionItem struct {
|
||||
ID string `json:"id"`
|
||||
Topic string `json:"topic"`
|
||||
Statement string `json:"statement"`
|
||||
Rationale string `json:"rationale"` // 行业先验推导依据
|
||||
Source string `json:"source"` // 默认 "inferred"
|
||||
}
|
||||
|
||||
// BlackboardState 结构化共享黑板
|
||||
type BlackboardState struct {
|
||||
Facts []FactItem `json:"facts"`
|
||||
Gaps []GapItem `json:"gaps"`
|
||||
Implications []ImplicationItem `json:"implications"`
|
||||
Assumptions []AssumptionItem `json:"assumptions,omitempty"`
|
||||
Fields map[string]string `json:"fields"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// StepAction 单步评估后的调整决策
|
||||
type StepAction string
|
||||
|
||||
const (
|
||||
StepActionContinue StepAction = "CONTINUE" // 无异常,正常按既定计划继续
|
||||
StepActionAddStep StepAction = "ADD_STEP" // 发现关键事实或缺口,动态追加补充步骤
|
||||
StepActionUpdateStep StepAction = "UPDATE_STEP" // 调整后续步骤的验收标准或指派角色
|
||||
StepActionSkipStep StepAction = "SKIP_STEP" // 前序步骤已充分覆盖,跳过冗余步骤
|
||||
)
|
||||
|
||||
// EvaluationResult 步骤评估报告
|
||||
type EvaluationResult struct {
|
||||
StepID string `json:"step_id"`
|
||||
Action StepAction `json:"action"`
|
||||
Reason string `json:"reason"`
|
||||
NewAssumptions []AssumptionItem `json:"new_assumptions,omitempty"` // 新增的基准假设
|
||||
ResolvedGaps []string `json:"resolved_gaps,omitempty"`
|
||||
DynamicStepsToAdd []StepSpec `json:"dynamic_steps_to_add,omitempty"`
|
||||
DynamicStepsToAlter []StepSpec `json:"dynamic_steps_to_alter,omitempty"`
|
||||
StepsToSkip []string `json:"steps_to_skip,omitempty"`
|
||||
}
|
||||
|
||||
// QualityReport 自动化质量门禁报告
|
||||
type QualityReport struct {
|
||||
Passed bool `json:"passed"`
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package squad
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAgentSpecEnhancements(t *testing.T) {
|
||||
spec := AgentSpec{
|
||||
Role: "biocompatibility_expert",
|
||||
Name: "生物相容性评估专员",
|
||||
Source: RoleSourceAdHoc,
|
||||
BaseRole: "engineer",
|
||||
Model: "MiniMax-M3",
|
||||
Tools: []string{"read", "write", "edit"},
|
||||
BashPermission: "deny",
|
||||
Responsibilities: []string{"生物相容性风险评估"},
|
||||
ForbiddenActions: []string{"严禁越权发布正式检验报告"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(spec)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal AgentSpec failed: %v", err)
|
||||
}
|
||||
|
||||
var parsed AgentSpec
|
||||
if err := json.Unmarshal(data, &parsed); err != nil {
|
||||
t.Fatalf("unmarshal AgentSpec failed: %v", err)
|
||||
}
|
||||
|
||||
if parsed.Source != RoleSourceAdHoc {
|
||||
t.Errorf("expected source %s, got %s", RoleSourceAdHoc, parsed.Source)
|
||||
}
|
||||
if parsed.BaseRole != "engineer" {
|
||||
t.Errorf("expected base_role engineer, got %s", parsed.BaseRole)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepSpecDynamicAdjustment(t *testing.T) {
|
||||
step := StepSpec{
|
||||
ID: "step_01_search",
|
||||
Role: "searcher",
|
||||
Title: "文献与标准检索",
|
||||
SubWorkspace: "tasks/01_search",
|
||||
Mode: "execute",
|
||||
AllowDynamicAdjustment: true,
|
||||
}
|
||||
|
||||
data, err := json.Marshal(step)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal StepSpec failed: %v", err)
|
||||
}
|
||||
|
||||
var parsed StepSpec
|
||||
if err := json.Unmarshal(data, &parsed); err != nil {
|
||||
t.Fatalf("unmarshal StepSpec failed: %v", err)
|
||||
}
|
||||
|
||||
if !parsed.AllowDynamicAdjustment {
|
||||
t.Errorf("expected AllowDynamicAdjustment to be true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkflowPlanPlanningMode(t *testing.T) {
|
||||
wf := WorkflowPlan{
|
||||
WorkflowID: "wf_test_123",
|
||||
TaskKey: "cleanroom_design",
|
||||
Title: "洁净厂房设计方案",
|
||||
PlanningMode: PlanModeAutonomousAdhoc,
|
||||
Status: "pending",
|
||||
Steps: []StepSpec{
|
||||
{
|
||||
ID: "step_01",
|
||||
Role: "organizer",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(wf)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal WorkflowPlan failed: %v", err)
|
||||
}
|
||||
|
||||
var parsed WorkflowPlan
|
||||
if err := json.Unmarshal(data, &parsed); err != nil {
|
||||
t.Fatalf("unmarshal WorkflowPlan failed: %v", err)
|
||||
}
|
||||
|
||||
if parsed.PlanningMode != PlanModeAutonomousAdhoc {
|
||||
t.Errorf("expected planning mode %s, got %s", PlanModeAutonomousAdhoc, parsed.PlanningMode)
|
||||
}
|
||||
if parsed.TaskKey != "cleanroom_design" {
|
||||
t.Errorf("expected task_key cleanroom_design, got %s", parsed.TaskKey)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlackboardAssumptions(t *testing.T) {
|
||||
bb := BlackboardState{
|
||||
Facts: []FactItem{
|
||||
{ID: "f1", Claim: "产品为无菌二类导管", Verified: true},
|
||||
},
|
||||
Assumptions: []AssumptionItem{
|
||||
{
|
||||
ID: "a1",
|
||||
Topic: "sterilization_method",
|
||||
Statement: "基准假设灭菌方式采用环氧乙烷(EO)灭菌,解析期设定为14天",
|
||||
Rationale: "客户未明确灭菌方式,依据二类无源无菌高分子导管临床通行工程惯例设定",
|
||||
Source: "inferred",
|
||||
},
|
||||
},
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
data, err := json.Marshal(bb)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal BlackboardState failed: %v", err)
|
||||
}
|
||||
|
||||
var parsed BlackboardState
|
||||
if err := json.Unmarshal(data, &parsed); err != nil {
|
||||
t.Fatalf("unmarshal BlackboardState failed: %v", err)
|
||||
}
|
||||
|
||||
if len(parsed.Assumptions) != 1 {
|
||||
t.Fatalf("expected 1 assumption, got %d", len(parsed.Assumptions))
|
||||
}
|
||||
if parsed.Assumptions[0].Source != "inferred" {
|
||||
t.Errorf("expected assumption source 'inferred', got '%s'", parsed.Assumptions[0].Source)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluationResult(t *testing.T) {
|
||||
res := EvaluationResult{
|
||||
StepID: "step_01_search",
|
||||
Action: StepActionAddStep,
|
||||
Reason: "检测到产品使用动物源牛心包,需动态追加生物相容性专题调研",
|
||||
NewAssumptions: []AssumptionItem{
|
||||
{
|
||||
ID: "a2",
|
||||
Topic: "animal_origin",
|
||||
Statement: "需执行GB/T 16886及ISO 22442动物源医疗器械病毒灭活评价",
|
||||
Source: "inferred",
|
||||
},
|
||||
},
|
||||
DynamicStepsToAdd: []StepSpec{
|
||||
{
|
||||
ID: "step_01_biocompatibility",
|
||||
Role: "biocompatibility_expert",
|
||||
Title: "动物源生物相容性与病毒灭活专项评估",
|
||||
SubWorkspace: "tasks/01_biocompatibility",
|
||||
Mode: "execute",
|
||||
},
|
||||
},
|
||||
StepsToSkip: []string{"step_02_market"},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal EvaluationResult failed: %v", err)
|
||||
}
|
||||
|
||||
var parsed EvaluationResult
|
||||
if err := json.Unmarshal(data, &parsed); err != nil {
|
||||
t.Fatalf("unmarshal EvaluationResult failed: %v", err)
|
||||
}
|
||||
|
||||
if parsed.Action != StepActionAddStep {
|
||||
t.Errorf("expected action %s, got %s", StepActionAddStep, parsed.Action)
|
||||
}
|
||||
if len(parsed.DynamicStepsToAdd) != 1 {
|
||||
t.Errorf("expected 1 dynamic step to add, got %d", len(parsed.DynamicStepsToAdd))
|
||||
}
|
||||
if len(parsed.StepsToSkip) != 1 || parsed.StepsToSkip[0] != "step_02_market" {
|
||||
t.Errorf("expected steps to skip ['step_02_market'], got %v", parsed.StepsToSkip)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user