Why: Background notice runs blocked chat, truncated results, and duplicated deliverable execution. Evidence: Focused run manager, card, server, recovery and race regressions pass locally; final combination checks are tracked in Dev. Impact: Persist full results and optional choices, fence dispatch by run identity, retain public child process, and repair legacy projections without a schema change. No paid model trial was run. Refs: feature/workbench-flow-completion
60 lines
1.6 KiB
Go
60 lines
1.6 KiB
Go
package cardsvc
|
|
|
|
import (
|
|
core "agent-system-core"
|
|
"strings"
|
|
)
|
|
|
|
func recordAnswer(card *core.ActivityCard, actionID, answer string) {
|
|
label := actionID
|
|
for _, action := range card.Actions {
|
|
if action.ID == actionID {
|
|
label = action.Label
|
|
break
|
|
}
|
|
}
|
|
body := []core.UINode{}
|
|
for _, node := range card.Body {
|
|
if node.Type == core.UIMarkdown && (strings.Contains(node.Markdown, "可在输入框自由输入") || strings.Contains(node.Markdown, "自由输入回应")) {
|
|
continue
|
|
}
|
|
body = append(body, node)
|
|
}
|
|
pairs := [][2]string{}
|
|
if label != "" {
|
|
pairs = append(pairs, [2]string{"你的选择", label})
|
|
}
|
|
if strings.TrimSpace(answer) != "" && answer != label {
|
|
pairs = append(pairs, [2]string{"补充说明", answer})
|
|
}
|
|
if len(pairs) > 0 {
|
|
body = append(body, core.UINode{Type: core.UIKV, KV: pairs})
|
|
}
|
|
card.Body = body
|
|
}
|
|
|
|
func (s *Service) presentResolved(owner string, card core.ActivityCard) core.ActivityCard {
|
|
if card.Status != core.CardResolved {
|
|
return card
|
|
}
|
|
// Already-recorded answers survive unchanged; old projections are repaired
|
|
// from their owner-scoped persisted HITL resolution without changing history.
|
|
for _, node := range card.Body {
|
|
for _, pair := range node.KV {
|
|
if pair[0] == "你的选择" || pair[0] == "补充说明" {
|
|
return card
|
|
}
|
|
}
|
|
}
|
|
ref, err := s.st.CardRef(owner, card.ID)
|
|
if err != nil || !strings.HasPrefix(ref, "hitl:") {
|
|
return card
|
|
}
|
|
resolution, err := s.st.HITLResolution(owner, strings.TrimPrefix(ref, "hitl:"))
|
|
if err != nil {
|
|
return card
|
|
}
|
|
recordAnswer(&card, "", resolution.Answer)
|
|
return card
|
|
}
|