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 { 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 }