Files
Agent-Squad/squad/router.go
T
weichenandCursor 75d8c08103 Add a router fast path and pass host tools through
Why: Simple tasks should finish as one assistant step, while complex tasks stay in leader mode, and every kernel step needs the host's tools and events.
Evidence: go test ./squad/ -count=1 passed, including direct route, leader entry, skill override, and delegation score fields.
Impact: Hosts can inject HostTools and OnEvent; a Router can choose direct or plan without changing product roles.
Refs: deliverable-quality-system B2
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 09:00:13 +00:00

77 lines
1.9 KiB
Go

package squad
import (
"context"
"fmt"
)
// RouteMode 是分诊结果。direct 不进入多角色流程;plan 进入 leader 委派。
type RouteMode string
const (
RouteDirect RouteMode = "direct"
RoutePlan RouteMode = "plan"
)
// RouteDecision 描述这一次目标怎么跑,以及它属于哪一族交付物。
type RouteDecision struct {
Mode RouteMode
Family string
Reason string
}
// Router 在规划之前做一次分诊。nil 决策表示不干预。
type Router interface {
Route(ctx context.Context, goal Goal) (*RouteDecision, error)
}
// applyRoute 把分诊写进运行元数据。显式 RunOptions.Mode 优先,分诊不覆盖。
func applyRoute(meta *RunMetadata, dec *RouteDecision, explicitMode string) {
if dec == nil || explicitMode != "" {
return
}
if meta.Metadata == nil {
meta.Metadata = map[string]string{}
}
meta.Metadata["route"] = string(dec.Mode)
if dec.Family != "" {
meta.Metadata["deliverable_family"] = dec.Family
}
if dec.Reason != "" {
meta.Metadata["route_reason"] = dec.Reason
}
switch dec.Mode {
case RouteDirect:
meta.Metadata["route_direct"] = "1"
case RoutePlan:
meta.Metadata["mode"] = "leader"
if meta.Metadata["leader_role"] == "" {
meta.Metadata["leader_role"] = "leader"
}
}
}
// directAssistantPlan 生成只有 assistant 一步的计划。
func directAssistantPlan(reg *RoleRegistry, goal Goal) (*SquadPlan, error) {
spec, ok := reg.Get("assistant")
if !ok {
return nil, fmt.Errorf("direct route requires a registered assistant role")
}
return &SquadPlan{
Squad: SquadConfig{Agents: []RoleSpec{spec}},
Workflow: WorkflowPlan{
WorkflowID: NewPlanID(),
Title: goal.Text,
Status: "pending",
Steps: []StepSpec{{
ID: "assistant",
Role: "assistant",
Title: goal.Text,
Targets: []string{"output.md"},
SubWorkspace: "tasks/01_assistant",
Status: "pending",
}},
},
}, nil
}