Version: 0.9.6.dev.260407

后端:
1.execute 正式终止协议补齐(abort / exhausted / completed 统一建模)
  - 更新model/common_state.go:新增 FlowTerminalStatus / FlowTerminalOutcome;补齐 Abort/Exhaust/ClearTerminalOutcome/IsCompleted 等统一终止语义
  - 更新model/execute_contract.go:新增 ExecuteActionAbort 与 AbortIntent;补齐 action 校验互斥规则
  - 更新prompt/execute.go:Plan/ReAct 两套 execute contract 升级到 V2,补充 abort 协议与 JSON 示例
2.graph 路由与 deliver 收口统一围绕 terminal outcome
  - 更新graph/common_graph.go:RoughBuild 改 branch;粗排异常可直接 Deliver;Execute 路由不再按“最后一轮”提前误收口
  - 更新node/execute.go:轮次耗尽改写为 Exhaust;接入 handleExecuteActionAbort;abort 不在 execute 直接对用户收口
  - 更新node/deliver.go:deliver summary 优先按 abort/exhausted 收口;不再无脑 Done;最终状态文案改为“本轮流程已结束”
  - 更新node/agent_nodes.go:仅 completed 路径写 schedule preview,aborted/exhausted 跳过
3.提示与状态摘要同步终止语义
  - 更新prompt/base.go:state summary 增加 terminal outcome 展示
前端:无 仓库:无
This commit is contained in:
Losita
2026-04-07 23:59:50 +08:00
parent cdedd3c968
commit 310cdfbcb7
8 changed files with 483 additions and 36 deletions

View File

@@ -28,6 +28,9 @@ const (
// ExecuteActionDone 表示整个任务已完成,可以进入最终交付。
ExecuteActionDone ExecuteAction = "done"
// ExecuteActionAbort 表示本轮流程应立即终止,并进入 deliver 做正式收口。
ExecuteActionAbort ExecuteAction = "abort"
)
// ExecuteDecision 是 execute prompt 单轮产出的统一决策结构。
@@ -43,6 +46,7 @@ type ExecuteDecision struct {
Reason string `json:"reason,omitempty"`
GoalCheck string `json:"goal_check,omitempty"`
ToolCall *ToolCallIntent `json:"tool_call,omitempty"`
Abort *AbortIntent `json:"abort,omitempty"`
}
// Normalize 统一清洗 execute 决策中的字符串字段。
@@ -57,6 +61,9 @@ func (d *ExecuteDecision) Normalize() {
if d.ToolCall != nil {
d.ToolCall.Normalize()
}
if d.Abort != nil {
d.Abort.Normalize()
}
}
// Validate 校验 execute 决策的最小合法性。
@@ -77,6 +84,9 @@ func (d *ExecuteDecision) Validate() error {
switch d.Action {
case ExecuteActionContinue:
if d.Abort != nil {
return fmt.Errorf("continue 动作不应携带 abort")
}
if d.ToolCall != nil {
return d.ToolCall.Validate()
}
@@ -85,22 +95,73 @@ func (d *ExecuteDecision) Validate() error {
if d.ToolCall != nil {
return fmt.Errorf("ask_user 动作不应携带 tool_call")
}
if d.Abort != nil {
return fmt.Errorf("ask_user 动作不应携带 abort")
}
return nil
case ExecuteActionConfirm:
if d.ToolCall == nil {
return fmt.Errorf("confirm 动作必须携带待确认的 tool_call")
}
if d.Abort != nil {
return fmt.Errorf("confirm 动作不应同时携带 abort")
}
return d.ToolCall.Validate()
case ExecuteActionNextPlan, ExecuteActionDone:
if d.ToolCall != nil {
return fmt.Errorf("%s 动作不应携带 tool_call", d.Action)
}
if d.Abort != nil {
return fmt.Errorf("%s 动作不应携带 abort", d.Action)
}
return nil
case ExecuteActionAbort:
if d.ToolCall != nil {
return fmt.Errorf("abort 动作不应携带 tool_call")
}
if d.Abort == nil {
return fmt.Errorf("abort 动作必须携带 abort 字段")
}
return d.Abort.Validate()
default:
return fmt.Errorf("未知 execute action: %s", d.Action)
}
}
// AbortIntent 表示 execute 阶段声明的正式终止意图。
//
// 说明:
// 1. code 是稳定机器码,便于后续前端/埋点识别终止类型;
// 2. user_message 是最终给用户看的收口文案;
// 3. internal_reason 只用于日志排查,允许更技术化。
type AbortIntent struct {
Code string `json:"code,omitempty"`
UserMessage string `json:"user_message"`
InternalReason string `json:"internal_reason,omitempty"`
}
// Normalize 清洗终止意图中的稳定字段。
func (a *AbortIntent) Normalize() {
if a == nil {
return
}
a.Code = strings.TrimSpace(a.Code)
a.UserMessage = strings.TrimSpace(a.UserMessage)
a.InternalReason = strings.TrimSpace(a.InternalReason)
}
// Validate 校验终止意图的最小可用性。
func (a *AbortIntent) Validate() error {
if a == nil {
return fmt.Errorf("abort 不能为空")
}
a.Normalize()
if a.UserMessage == "" {
return fmt.Errorf("abort.user_message 不能为空")
}
return nil
}
// ToolCallIntent 表示 execute 阶段申报的工具调用意图。
//
// 设计目的: