Files
Agent-Squad/squad/models.go
T
weichenandCursor 8e987bf535
ci / vet-and-test (pull_request) Failing after 1s
ci / docker-checkout-hostgateway (pull_request) Failing after 3s
Persist step approvals and guard squad HTTP entry points
Why: A step confirmation cancelled the whole run, approvals and repair budget vanished on restart, and the HTTP server accepted anonymous and oversized requests.
Evidence: GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./... && GOWORK=off go test -race ./squad/... passed. scripts/submodule-consistency.sh ok.
Impact: Approve and skip apply to one step; runstate.json and unix flock survive restart; wakeup leaves permission holds pending; serve defaults to loopback and requires a token off-loopback.
Refs: Q1 Q2 Q3 Q4 Q5 Q8 Q9 Q14 Q15 Q16
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 01:48:10 +00:00

288 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package squad 提供通用智能体小队编排底座:角色注册、目标规划、动态执行、
// 黑板协同与 HITL 挂起/恢复。本包不含任何预设角色或任务模板。
package squad
import "time"
// RoleSource 标识角色来源。
type RoleSource string
const (
// RoleSourceRegistered 表示外部注册的角色(配置文件/API/CLI)。
RoleSourceRegistered RoleSource = "registered"
// RoleSourceDerived 表示规划器或用户在运行期派生的特设角色。
RoleSourceDerived RoleSource = "derived"
)
// RoleSpec 声明一个小队角色的完整设定。空表起步:库不预置任何角色。
// BashPermission 三态(执行类工具的授权档位)。
const (
BashPermissionAllow = "allow" // 装配执行工具,无人工门
BashPermissionAsk = "ask" // 装配执行工具,步骤前 HITL permission 门
BashPermissionDeny = "deny" // 不装配执行工具(默认)
)
type RoleSpec struct {
Role string `json:"role"`
Name string `json:"name"`
Source RoleSource `json:"source,omitempty"`
BaseRole string `json:"base_role,omitempty"`
Backend string `json:"backend,omitempty"` // 绑定的智能体名:stub/llm/agent-native/pi-agent/自定义注册名
Model string `json:"model,omitempty"` // 角色级模型(backend 支持时生效)
ToolProfile string `json:"tool_profile,omitempty"` // agent-native ToolProfile:workspace/reasoning
Tools []string `json:"tools,omitempty"`
Skills []string `json:"skills,omitempty"` // 技能标识(backend 支持时注入)
BashPermission string `json:"bash_permission"` // allow / ask / deny
Responsibilities []string `json:"responsibilities,omitempty"`
ForbiddenActions []string `json:"forbidden_actions,omitempty"`
Keywords []string `json:"keywords,omitempty"` // 规则规划器推荐与匹配用
Instructions string `json:"instructions,omitempty"` // 内联指令(优先)
InstructionsFile string `json:"instructions_file,omitempty"` // 指令文件(数据目录相对或绝对路径)
HitlPolicy *HitlPolicy `json:"hitl_policy,omitempty"` // 角色级 HITL 策略(覆盖全局)
// MaxConcurrentTasks 该角色同时执行步骤的上限(<=1 视为 1);
// 引擎在解析后端时以并发限流包装实现(对象级串行语义)。
MaxConcurrentTasks int `json:"max_concurrent_tasks,omitempty"`
}
// Goal 一次小队运行的目标输入。
type Goal struct {
Text string `json:"text"`
Materials []MaterialFile `json:"materials,omitempty"`
Constraints map[string]string `json:"constraints,omitempty"`
HitlMode HitlMode `json:"hitl_mode,omitempty"` // 覆盖全局策略
HitlTimeout time.Duration `json:"hitl_timeout,omitempty"`
}
// MaterialFile 一份输入材料(文件字节或磁盘路径二选一)。
type MaterialFile struct {
Filename string `json:"filename"`
Path string `json:"path,omitempty"`
Content []byte `json:"content,omitempty"`
}
// Blueprint 已注册的任务模板:命中的 Goal 走基线工作流,未注册走自主规划。
type Blueprint struct {
Key string `json:"key"` // 模板键(可由 BlueprintMatcher 匹配 Goal.Text)
Title string `json:"title"`
Match []string `json:"match,omitempty"` // 关键词命中即视为命中模板
Description string `json:"description,omitempty"`
Agents []RoleSpec `json:"agents,omitempty"` // 默认编制(引用已注册角色或内联角色)
Steps []StepSpec `json:"steps"`
Template string `json:"template,omitempty"` // 交付物骨架模板(Markdown)
}
// PlanningMode 规划模式。
type PlanningMode string
const (
PlanModeBlueprint PlanningMode = "blueprint" // 命中模板:基线步骤 + 动态微调
PlanModeAutonomous PlanningMode = "autonomous" // 未命中模板:规划器自主拆解
)
// StepSpec 单个步骤规格。
type StepSpec struct {
ID string `json:"id"`
Role string `json:"role"`
Title string `json:"title"`
SubWorkspace string `json:"sub_workspace,omitempty"` // 相对子路径,缺省 tasks/NN_role
Mode string `json:"mode,omitempty"` // 预留
Parallel bool `json:"parallel"`
Needs []string `json:"needs,omitempty"`
Targets []string `json:"targets,omitempty"` // 期望交付物相对路径,缺省 output.md
Status string `json:"status"` // pending, running, completed, failed, skipped
// Attempts 该步骤进入 running 的次数。中断恢复用它决定 auto 策略是否还能重试。
Attempts int `json:"attempts,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
Error string `json:"error,omitempty"`
// RequiresApproval 为 true 时,该步骤启动前进入 HITL 计划确认。
RequiresApproval bool `json:"requires_approval,omitempty"`
// IntentID 非空 = 系统功能步:不经 BackendResolver/智能体,由 IntentRunner 直接执行
//(计划确定性校验:意图须在目录内且必填槽位齐)。
IntentID string `json:"intent_id,omitempty"`
// IntentSlots 系统功能步的槽位取值(规划者按目录填写)。
IntentSlots map[string]string `json:"intent_slots,omitempty"`
// AllowDynamicAdjustment 允许评估器在步骤后做动态调整(加步/跳步/改步)。
AllowDynamicAdjustment bool `json:"allow_dynamic_adjustment,omitempty"`
// Critical: nil(默认)= 关键步骤失败即终止;false = 非关键,失败降级继续。
Critical *bool `json:"critical,omitempty"`
// Skills 覆盖角色默认技能。空 = 用角色自己的技能列表。
Skills []string `json:"skills,omitempty"`
// MinScore 质检总分下限。0 = 不额外设门槛,只看 Checker.Passed。
MinScore int `json:"min_score,omitempty"`
}
// IsCritical 报告步骤是否关键(nil 视为关键)。
func (s StepSpec) IsCritical() bool { return s.Critical == nil || *s.Critical }
// WorkflowPlan 编排清单(与产品 squad workflow.json 字段兼容)。
type WorkflowPlan struct {
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, degraded, cancelled
CurrentStepIndex int `json:"current_step_index"`
Steps []StepSpec `json:"steps"`
}
// SquadConfig 激活的小队编制(与产品 squad.json 字段兼容)。
type SquadConfig struct {
SquadName string `json:"squad_name"`
Version string `json:"version"`
Agents []RoleSpec `json:"agents"`
}
// ---- 黑板 ----
// FactItem 黑板事实项。
type FactItem struct {
ID string `json:"id"`
Claim string `json:"claim"`
Source string `json:"source"`
Verified bool `json:"verified"`
}
// GapItem 黑板缺口项;Blocking=true 且未解决时触发 HITL 挂起。
// WaitRunID/WaitField 非空时,该缺口的 HITL 请求携带等待条件:
// 目标运行进入终态 / 黑板字段出现时自动唤醒续跑(等事件而非只等人)。
type GapItem struct {
ID string `json:"id"`
Item string `json:"item"`
Owner string `json:"owner"` // user / agent
Blocking bool `json:"blocking"` // 是否阻塞后续推进
Resolved bool `json:"resolved"`
WaitRunID string `json:"wait_run_id,omitempty"` // 等待指定运行到达终态
WaitField string `json:"wait_field,omitempty"` // 等待黑板出现该字段
}
// ImplicationItem 黑板推导项。
type ImplicationItem struct {
ID string `json:"id"`
Topic string `json:"topic"`
Statement string `json:"statement"`
}
// AssumptionItem 黑板假设项(auto HITL 模式下作为阻塞缺口的兜底假设来源)。
type AssumptionItem struct {
ID string `json:"id"`
Topic string `json:"topic"`
Statement string `json:"statement"`
Rationale string `json:"rationale"`
Source string `json:"source"` // 默认 inferred;HITL 兜底时为 fallback
}
// BlackboardState 结构化共享黑板(与产品 blackboard.json 字段兼容)。
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"`
}
// ContextItem 工作区上下文资源条目。
type ContextItem struct {
File string `json:"file"`
Description string `json:"description"`
AuthorityLevel string `json:"authority_level"` // authoritative, primary_evidence, reference_standard, supplementary, inferred
Guidance string `json:"guidance"`
}
// ContextIndex 上下文索引。
type ContextIndex struct {
Items []ContextItem `json:"context_items"`
}
// QualityReport 交付检查报告。
type QualityReport struct {
Passed bool `json:"passed"`
Score float64 `json:"score"`
Violations []string `json:"violations,omitempty"`
MissingSections []string `json:"missing_sections,omitempty"`
Placeholders []string `json:"placeholders,omitempty"`
// ManualPass 为 true 时表示质检未过但经 HITL 人工放行。
ManualPass bool `json:"manual_pass,omitempty"`
CheckedAt time.Time `json:"checked_at"`
}
// Manifest 执行清单与防篡改审计。
type Manifest struct {
ManifestVersion string `json:"manifest_version"`
WorkspaceID string `json:"workspace_id"`
GeneratedAt time.Time `json:"generated_at"`
Deliverable string `json:"deliverable"`
Files map[string]string `json:"files"` // relPath -> sha256
QualityReport QualityReport `json:"quality_report"`
DurationMs int64 `json:"duration_ms"`
}
// RunMetadata 工作区元信息(workspace.json)。
type RunMetadata struct {
ID string `json:"id"`
Goal Goal `json:"goal"`
Status string `json:"status"`
Backend string `json:"backend,omitempty"` // 默认后端名(角色级 Backend 优先)
Planner string `json:"planner,omitempty"`
WorkDir string `json:"work_dir"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
// RunStatus 一次运行的对外状态(含 HITL 挂起态)。
type RunStatus string
const (
RunCreated RunStatus = "created"
RunPlanning RunStatus = "planning"
RunAwaitingClarification RunStatus = "awaiting_clarification" // HITL:规划歧义,等待澄清
RunAwaitingConfirmation RunStatus = "awaiting_confirmation" // HITL:计划待确认
RunExecuting RunStatus = "executing"
RunWaitingHuman RunStatus = "waiting_human" // HITL:执行中挂起(缺口/审批/权限/质检)
RunQualityReview RunStatus = "quality_review" // HITL:质检超限转人工
RunCompleted RunStatus = "completed"
RunDegraded RunStatus = "degraded"
RunFailed RunStatus = "failed"
RunCancelled RunStatus = "cancelled"
)
// IsHeld 返回该状态是否为 HITL 挂起态(等待人工回应)。
func (s RunStatus) IsHeld() bool {
return s == RunAwaitingClarification || s == RunAwaitingConfirmation ||
s == RunWaitingHuman || s == RunQualityReview
}
// Terminal 报告该状态是否为终态。
func (s RunStatus) Terminal() bool {
switch s {
case RunCompleted, RunDegraded, RunFailed, RunCancelled:
return true
}
return false
}
// RunResult 引擎单次推进的返回(Run/Respond/Resume 共用)。
type RunResult struct {
RunID string `json:"run_id"`
Status RunStatus `json:"status"`
Plan *WorkflowPlan `json:"plan,omitempty"`
Squad *SquadConfig `json:"squad,omitempty"`
Pending *HumanRequest `json:"pending,omitempty"` // 挂起时的人工请求
Deliverable string `json:"deliverable,omitempty"`
Quality *QualityReport `json:"quality,omitempty"`
Summary string `json:"summary,omitempty"`
Error string `json:"error,omitempty"`
WorkDir string `json:"work_dir,omitempty"`
// Usage 按角色聚合的模型用量(步骤执行结果累计)。
Usage map[string]Usage `json:"usage,omitempty"`
}
// Usage 单角色的 token 用量(多步骤累计)。
type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
Steps int `json:"steps"`
}