Files
Agent-System/internal/coordinator/action_planner.go
T
WeiCHENandCursor 24478ec383 feat(intent): Phase 5 V2 shadow gray flags and IntentPlan execution
Add env-based feature flags (intent_v2_shadow/decision, multi_intent,
workflow_intents), V1/V2 shadow diff reporting, expectation_plus_new plan
building, ranked-frame L2 conflict gate, and coordinator sequential query
plan execution with confirm-step deferral.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 02:50:21 +00:00

144 lines
3.8 KiB
Go

package coordinator
import (
"context"
"fmt"
"strings"
"chat-agent-system/internal/intent"
)
func candidateFromFrame(frame intent.IntentFrameV2) *intent.CandidateIntent {
slots := make(map[string]string, len(frame.Slots))
for k, v := range frame.Slots {
slots[k] = v.Value
}
return &intent.CandidateIntent{
Intent: frame.LegacyIntent,
Confidence: frame.Score,
FilledSlots: slots,
Reasoning: fmt.Sprintf("IntentPlan step action=%s", frame.ActionKey),
}
}
// executeIntentPlan 顺序执行有限多意图计划(Phase 5:仅安全只读组合自动执行)
func (e *CoordinatorEngine) executeIntentPlan(
ctx context.Context,
recRes *intent.IntentRecognitionResult,
userCtx *UserProjectContext,
) (*CoordinationResult, error) {
plan := recRes.IntentPlan
if plan == nil || len(plan.Steps) == 0 || !intent.CurrentFeatureFlags().MultiIntentEnabled {
return nil, nil
}
var parts []string
var last *CoordinationResult
var pendingConfirm *intent.IntentPlanStep
for _, step := range plan.Steps {
cand := candidateFromFrame(step.Frame)
if step.Frame.Relation == intent.RelationExpectationHit ||
step.Frame.Goal == intent.GoalDecide ||
step.Frame.Goal == intent.GoalControl && isConfirmRequiredStep(&step) {
pendingConfirm = &step
continue
}
if !isAutoExecutableQueryStep(&step) {
return nil, nil
}
stepRes, err := e.dispatchIntentHandler(ctx, cand, userCtx, recRes.RawInput)
if err != nil {
if plan.FailureMode == "stop_on_first_failure" {
return nil, err
}
continue
}
if stepRes == nil {
continue
}
last = stepRes
if stepRes.NaturalReply != "" {
parts = append(parts, fmt.Sprintf("**步骤 %s** %s", step.StepID, stepRes.NaturalReply))
}
}
if len(parts) == 0 && pendingConfirm == nil {
return nil, nil
}
reply := strings.Join(parts, "\n\n")
if pendingConfirm != nil {
confirmNote := fmt.Sprintf(
"另:您同时提到了「%s」。该操作需单独确认后再执行,请回复「确认」或选择对应选项。",
pendingConfirm.Frame.ActionKey,
)
if reply == "" {
reply = confirmNote
} else {
reply += "\n\n" + confirmNote
}
}
if last == nil {
last = &CoordinationResult{UpdatedContext: userCtx}
}
last.NaturalReply = reply
last.Intent = recRes.TopIntent.Intent
last.Branch = recRes.Branch
last.UpdatedContext = userCtx
if pendingConfirm != nil && userCtx.PendingExpectation != nil {
last.NextExpectation = userCtx.PendingExpectation
}
return last, nil
}
func isAutoExecutableQueryStep(step *intent.IntentPlanStep) bool {
if step == nil {
return false
}
return step.Frame.Goal == intent.GoalQuery || intent.IsQueryLegacyIntent(step.Frame.LegacyIntent)
}
func isConfirmRequiredStep(step *intent.IntentPlanStep) bool {
if step == nil {
return false
}
spec, ok := intent.DefaultRegistry().Get(step.Frame.ActionKey)
return ok && spec.RequiresConfirm
}
func (e *CoordinatorEngine) dispatchIntentHandler(
ctx context.Context,
cand *intent.CandidateIntent,
userCtx *UserProjectContext,
rawInput string,
) (*CoordinationResult, error) {
if cand == nil {
return nil, nil
}
switch cand.Intent {
case intent.IntentQueryProgress:
return e.handleQueryProgress(ctx, cand, userCtx, rawInput)
case intent.IntentQueryRegulations:
return e.handleQueryRegulations(ctx, cand, userCtx)
case intent.IntentQuerySimilarCases:
return e.handleQuerySimilarCases(ctx, cand, userCtx)
case intent.IntentQueryUserRights:
return e.handleQueryUserRights(ctx, cand, userCtx)
case intent.IntentQueryWorkflowStatus:
return e.handleQueryWorkflowStatus(ctx, cand, userCtx)
case intent.IntentQueryDocStatus:
return e.handleQueryDocStatus(ctx, cand, userCtx)
case intent.IntentRunStatusQuery:
return e.handleRunStatusQuery(ctx, cand, userCtx)
case intent.IntentHelpCapabilities:
return e.handleHelpCapabilities(ctx, cand, userCtx)
default:
return nil, nil
}
}