Files
weichen 76ddf4dd35 feat(ctx): surface dialogue conflict confirmation cards to triggering user
Capture trigger_user HITL expectations from dialogue adjudication (previously
dropped at the bizdev call site), project them as chat confirmation cards via
taskrun OnTerminal (exactly-once), arm the session PendingExpectation, and
handle confirm_context_fact hits through the supplement-info blackboard path.
Decline (纠正) guides the user to state the correct fact.
2026-09-25 21:01:37 +00:00

57 lines
2.2 KiB
Go

package coordinator
import (
"fmt"
"strings"
"chat-agent-system/internal/intent"
)
// TargetActionContextFact is the pending-expectation action produced by the
// dialogue-context conflict adjudication (bizdev buildDialoguePackageForRun).
const TargetActionContextFact = "confirm_context_fact"
// handleConfirmActionHit serves the CONFIRM_ACTION expectation hit. Today the
// only async-armed expectation of this shape is the dialogue-context conflict
// card: confirming absorbs the winning fact into the project blackboard via
// the supplement-info path (memory + blackboard.json + OnSupplement hook).
// Unknown or un-armed confirmations fall back to the generic acknowledgement.
func (e *CoordinatorEngine) handleConfirmActionHit(cand *intent.CandidateIntent, userCtx *UserProjectContext, branch intent.ResolutionBranch) (*CoordinationResult, error) {
pending := userCtx.PendingExpectation
if pending == nil || pending.TargetAction != TargetActionContextFact {
return e.genericAcknowledgement(cand, userCtx, branch), nil
}
factKey := strings.TrimSpace(pending.Payload["fact_key"])
factVal := strings.TrimSpace(pending.Payload["winning_value"])
if factKey == "" || factVal == "" {
userCtx.applyPending(nil)
return &CoordinationResult{
Status: StatusAccepted,
Intent: intent.IntentConfirmAction,
Branch: branch,
NaturalReply: "确认卡信息已失效(缺少事实键或推荐值),本次不做黑板变更。如仍有冲突请重新触发任务。",
UpdatedContext: userCtx,
ClearExpectation: true,
}, nil
}
patched := &intent.CandidateIntent{
Intent: intent.IntentSupplementInfo,
Confidence: cand.Confidence,
Branch: branch,
FilledSlots: map[string]string{
intent.SlotFactKey: factKey,
intent.SlotFactValue: factVal,
},
Reasoning: fmt.Sprintf("用户确认对话冲突采信 [%s=%s]", factKey, factVal),
}
res, err := e.handleSupplementInfo(patched, userCtx)
if err != nil || res == nil {
return res, err
}
res.Intent = intent.IntentConfirmAction
res.NaturalReply = fmt.Sprintf("✅ 冲突确认完成:已按您的确认采信「%s」=「%s」,并同步项目黑板。\n\n%s", factKey, factVal, res.NaturalReply)
return res, nil
}