Files
Agent-System/internal/coordinator/engine_run.go
T
weichen d55488ae37 feat(coordinator): 用智能体叙述查询、帮助与操作回执
确定性事实仍由代码生成;PI Agent 只组织语言,失败或关闭开关时回退原模板。安全拦截与确认提问保持模板。
2026-09-28 03:25:06 +00:00

141 lines
5.0 KiB
Go

package coordinator
import (
"context"
"fmt"
"chat-agent-system/internal/intent"
)
func isRunActionConfirmed(userCtx *UserProjectContext, targetAction string) bool {
if userCtx == nil || userCtx.PendingExpectation == nil {
return false
}
return userCtx.PendingExpectation.TargetAction == targetAction
}
func (e *CoordinatorEngine) handleRunStatusQuery(ctx context.Context, _ *intent.CandidateIntent, userCtx *UserProjectContext) (*CoordinationResult, error) {
workDir := userCtx.WorkDir
reply := "📊 **运行状态查询(只读)**\n\n"
if workDir != "" {
reply += fmt.Sprintf("• 最近工作区:`%s`\n• 您可以在任务面板查看该运行的阶段、失败原因与产物摘要。\n", workDir)
} else {
reply += "• 当前会话未绑定具体工作区。请指定要查询的运行任务,或先在界面打开失败任务详情。\n"
}
return e.applyNarrative(ctx, userCtx, "handleRunStatusQuery", "", "", &CoordinationResult{
Status: StatusAccepted,
Intent: intent.IntentRunStatusQuery,
NaturalReply: reply,
UpdatedContext: userCtx,
}), nil
}
func (e *CoordinatorEngine) handleRunResume(ctx context.Context, cand *intent.CandidateIntent, userCtx *UserProjectContext) (*CoordinationResult, error) {
workDir := cand.FilledSlots[intent.SlotWorkDir]
if workDir == "" {
workDir = userCtx.WorkDir
}
if workDir == "" {
msg := cand.ClarificationQuestion
if msg == "" {
msg = "续跑需要绑定目标工作区。请说明要恢复哪一次失败运行,或在工作区面板选择「继续」。"
}
return &CoordinationResult{
Status: StatusClarificationRequired,
Intent: intent.IntentRunResume,
ClarificationPrompt: msg,
NaturalReply: msg,
UpdatedContext: userCtx,
}, nil
}
if isRunActionConfirmed(userCtx, "run.resume") {
userCtx.applyPending(nil)
return e.applyNarrative(ctx, userCtx, "handleRunResume", "", "这是用户已确认后续跑的受理通报。必须保留工作区路径,并说明正在发起续跑,不得宣称运行已经结束。", &CoordinationResult{
Status: StatusAccepted,
Intent: intent.IntentRunResume,
NaturalReply: fmt.Sprintf("正在为您续跑工作区 `%s`…", workDir),
UpdatedContext: userCtx,
PendingAction: &PendingAction{
Kind: "taskrun.resume",
WorkDir: workDir,
},
ClearExpectation: true,
}), nil
}
msg := fmt.Sprintf(
"已理解您要续跑工作区 `%s`(复用已有上下文)。请在任务面板确认「继续」,或回复「确认续跑」后我将为您发起 resume 请求。",
workDir,
)
return &CoordinationResult{
Status: StatusClarificationRequired,
Intent: intent.IntentRunResume,
NaturalReply: msg,
ClarificationPrompt: msg,
UpdatedContext: userCtx,
NextExpectation: &intent.PendingExpectation{
ExpectedIntent: intent.IntentRunResume,
TargetAction: "run.resume",
Prompt: "确认续跑长任务",
AllowAffirmative: true,
Payload: map[string]string{
intent.SlotWorkDir: workDir,
},
DefaultOption: &intent.ExpectationOption{
OptionID: "confirm_resume",
Title: "确认续跑",
Intent: intent.IntentRunResume,
Slots: map[string]string{
intent.SlotWorkDir: workDir,
},
},
},
}, nil
}
func (e *CoordinatorEngine) handleRunRestart(ctx context.Context, cand *intent.CandidateIntent, userCtx *UserProjectContext) (*CoordinationResult, error) {
if isRunActionConfirmed(userCtx, "run.restart") {
userCtx.applyPending(nil)
taskKey := cand.FilledSlots["task_key"]
if taskKey == "" && userCtx.TaskState != nil {
taskKey = userCtx.TaskState.ActiveTask
}
return e.applyNarrative(ctx, userCtx, "handleRunRestart", "", "这是用户已确认后的重新启动受理通报。必须说明正在重新启动,不得宣称任务已经完成。", &CoordinationResult{
Status: StatusAccepted,
Intent: intent.IntentRunRestart,
NaturalReply: "正在为您重新启动任务…",
UpdatedContext: userCtx,
ClearExpectation: true,
PendingAction: &PendingAction{
Kind: "taskrun.restart",
TaskKey: taskKey,
WorkDir: userCtx.WorkDir,
},
}), nil
}
msg := "已理解您希望重新运行任务(将创建新工作区,保留原始意图但不复用失败现场)。这是高风险操作,请确认后再执行。"
if cand.ClarificationQuestion != "" {
msg = cand.ClarificationQuestion
}
return &CoordinationResult{
Status: StatusClarificationRequired,
Intent: intent.IntentRunRestart,
NaturalReply: msg,
ClarificationPrompt: msg,
UpdatedContext: userCtx,
NextExpectation: &intent.PendingExpectation{
ExpectedIntent: intent.IntentRunRestart,
TargetAction: "run.restart",
Prompt: "确认重新运行长任务",
AllowAffirmative: false,
DefaultOption: &intent.ExpectationOption{
OptionID: "confirm_restart",
Title: "确认重新运行",
Intent: intent.IntentRunRestart,
},
},
}, nil
}