Why: Reconcile interrupted dispatch without spending another model request. Evidence: Core package tests pass locally; integration exercises acceptance and recovery. Impact: Add one optional persisted run identifier. Refs: feature/workbench-flow-completion
90 lines
4.4 KiB
Go
90 lines
4.4 KiB
Go
package core
|
|
|
|
import "time"
|
|
|
|
// ActivityCard:异步任务/待确认事项的统一状态对象——右栏收件箱的条目。
|
|
// 与一次性消息相对:卡片是有生命周期的状态(进行中→完成/待办→已决/失败/弃置),
|
|
// 由服务端权威维护,经 card.* 事件驱动前端投影;确认动作回写对话时间线并留审计。
|
|
//
|
|
// 生命周期:active → done | action_required → resolved | failed | dismissed。
|
|
// Kind 决定卡身的默认内容组合(progress 流式区 / compare 对比 / review-list 裁决清单…),
|
|
// Body 用 UI 有限词汇渲染;插件可扩展 Kind(前端按未知 kind 走通用卡渲染)。
|
|
type ActivityCard struct {
|
|
ID ID `json:"id"`
|
|
// ProjectID/ConversationID 定位归属;ConversationID 为空表示项目级卡片(远期跨会话收件箱)。
|
|
ProjectID ID `json:"projectId"`
|
|
ConversationID ID `json:"conversationId,omitempty"`
|
|
SourceRunID ID `json:"sourceRunId,omitempty"` // 溯源:产生卡片的 run
|
|
AnchorMessageID ID `json:"anchorMessageId,omitempty"` // 互定位:出生消息(↙ 定位到对话)
|
|
Kind CardKind `json:"kind"`
|
|
Title string `json:"title"`
|
|
Status CardStatus `json:"status"`
|
|
Tone string `json:"tone,omitempty"` // ok | warn | danger | info
|
|
Body []UINode `json:"body,omitempty"`
|
|
Actions []UIAction `json:"actions,omitempty"` // 走命令总线;未绑定 command 降级为发消息
|
|
Pinned bool `json:"pinned,omitempty"`
|
|
Work *WorkCard `json:"work,omitempty"` // optional background-work snapshot; never a foreground approval
|
|
CreatedAt time.Time `json:"createdAt"`
|
|
UpdatedAt time.Time `json:"updatedAt"`
|
|
}
|
|
|
|
// WorkCard keeps the complete saved result and an optional, non-blocking next step
|
|
// on the original task. Reading and answering do not change the result version.
|
|
type WorkCard struct {
|
|
Result string `json:"result,omitempty"`
|
|
ResultVersion int `json:"resultVersion"`
|
|
ReadVersion int `json:"readVersion"`
|
|
CompletedAt *time.Time `json:"completedAt,omitempty"`
|
|
Decision *WorkDecision `json:"decision,omitempty"`
|
|
}
|
|
|
|
type WorkDecision struct {
|
|
RunID ID `json:"runId,omitempty"` // reserved child identity; reconciles acceptance after restart without rerunning
|
|
Mode string `json:"mode"` // single | multiple
|
|
State string `json:"state"` // open | deferred | dispatching | submitted
|
|
Options []WorkOption `json:"options,omitempty"`
|
|
SelectedIDs []string `json:"selectedIds,omitempty"`
|
|
FreeText string `json:"freeText,omitempty"`
|
|
RespondedAt *time.Time `json:"respondedAt,omitempty"`
|
|
}
|
|
|
|
type WorkOption struct {
|
|
ID string `json:"id"`
|
|
Label string `json:"label"`
|
|
}
|
|
|
|
// WorkCardAction is version-fenced. Presentation-only opens never mark a result read.
|
|
type WorkCardAction struct {
|
|
ResultVersion int `json:"resultVersion"`
|
|
SelectedIDs []string `json:"selectedIds,omitempty"`
|
|
FreeText string `json:"freeText,omitempty"`
|
|
}
|
|
|
|
type CardKind string
|
|
|
|
const (
|
|
CardKindProgress CardKind = "progress" // 后台任务进度(流式区 + 进度行)
|
|
CardKindConfirm CardKind = "confirm" // 待确认(相关性/冲突/门禁/投影)
|
|
CardKindCompare CardKind = "compare" // 左右对比(基线 vs 新内容)
|
|
CardKindReviewList CardKind = "review-list" // 逐条裁决清单(候选边/缺项)
|
|
CardKindResult CardKind = "result" // 结果与产物(结论 + 来源 + 打开入口)
|
|
CardKindError CardKind = "error" // 失败显式呈现(可重试/可取回)
|
|
CardKindStatus CardKind = "status" // 常态状态卡(文档进度等)
|
|
)
|
|
|
|
type CardStatus string
|
|
|
|
const (
|
|
CardActive CardStatus = "active" // 进行中
|
|
CardActionRequired CardStatus = "action_required" // 待用户处理
|
|
CardDone CardStatus = "done" // 完成(未读结果)
|
|
CardResolved CardStatus = "resolved" // 已确认/已处理(盖章留痕)
|
|
CardFailed CardStatus = "failed"
|
|
CardDismissed CardStatus = "dismissed" // 用户关闭(非确认语义)
|
|
)
|
|
|
|
// Terminal 报告卡片是否处于终态(终态卡进入"已完成"可收纳区)。
|
|
func (s CardStatus) Terminal() bool {
|
|
return s == CardResolved || s == CardFailed || s == CardDismissed
|
|
}
|