Why: 卡流机制(CF1)需要消息部件正式引用收件箱 ActivityCard——submit_card 产卡时卡片为产物权威载体,消息只存引用+锚点渲染(原仅能从 data 字符串里正则抠 card:<id>)。 Evidence: go test ./... 通过;golden message.json 增 card 引用部件锁定 cardId 线格式(-update 重生成后逐字节一致)。 Impact: CardPart 增可选 cardId(omitempty,旧数据零影响);ts/types.ts 同步,镜像经 make contracts 再生成。 Refs: Dev 任务卡 feature/cardflow-r1;提案 cardflow-and-process-split(编制中)。
231 lines
7.8 KiB
Go
231 lines
7.8 KiB
Go
// Package core 定义 Agent-System 的核心契约:领域模型、流式事件、HITL 卡片、
|
||
// 插件 API、设置与 UI 词汇。本仓只含契约与少量纯函数,不含实现、不含 I/O。
|
||
//
|
||
// JSON 标签(camelCase)是前后端与插件共同的线格式契约;TS 类型镜像见 ts/types.ts,
|
||
// 黄金样本见 testdata/golden/(conformance 测试保证 Go 序列化与样本一致)。
|
||
package core
|
||
|
||
import "time"
|
||
|
||
// ---- 标识 ----
|
||
|
||
// ID 形态为 <kind>_<hex12>;生成由后端负责,契约只约束非空与唯一。
|
||
type ID = string
|
||
|
||
// ---- 项目与会话 ----
|
||
|
||
// Owner 是租户标识(多租户主线,设计 D5/D16):空串 = 单租户默认(嵌入式档/
|
||
// 未启用认证时的隐式 owner)。API 层强制 owner 过滤,跨租户访问一律 NotFound。
|
||
type Project struct {
|
||
ID ID `json:"id"`
|
||
Owner ID `json:"owner,omitempty"`
|
||
Name string `json:"name"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
Settings map[string]any `json:"settings,omitempty"` // 项目层设置覆盖(4.9 覆盖链)
|
||
}
|
||
|
||
type Conversation struct {
|
||
ID ID `json:"id"`
|
||
ProjectID ID `json:"projectId"`
|
||
Owner ID `json:"owner,omitempty"` // 冗余自项目,查询过滤用
|
||
Title string `json:"title"`
|
||
ProfileID ID `json:"profileId,omitempty"` // 空为默认画像
|
||
Pinned bool `json:"pinned,omitempty"` // 侧栏置顶(方案 A P6/P8:本端组织偏好,服务端权威)
|
||
Archived bool `json:"archived,omitempty"` // 归档:列表默认隐藏,数据保留
|
||
AllowCrossRead bool `json:"allowCrossRead,omitempty"` // 跨会话出站:本会话读取同项目其他会话记录(需项目开关 crossSession.read)
|
||
CrossPrivate bool `json:"crossPrivate,omitempty"` // 跨会话入站:私有会话,不被他读、不出现在他方列表
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// ---- 消息与部件 ----
|
||
|
||
type Role string
|
||
|
||
const (
|
||
RoleUser Role = "user"
|
||
RoleAssistant Role = "assistant"
|
||
RoleSystem Role = "system"
|
||
)
|
||
|
||
// PartType 区分消息成分;前端按类型查渲染器,未知类型静默忽略(原则 6)。
|
||
type PartType string
|
||
|
||
const (
|
||
PartText PartType = "text"
|
||
PartThinking PartType = "thinking"
|
||
PartToolCall PartType = "tool_call"
|
||
PartToolResult PartType = "tool_result"
|
||
PartArtifactRef PartType = "artifact_ref"
|
||
PartHITL PartType = "hitl"
|
||
PartPlan PartType = "plan"
|
||
PartError PartType = "error"
|
||
PartCard PartType = "card" // 插件自定义卡片(Data 为 UI schema)
|
||
)
|
||
|
||
type Message struct {
|
||
ID ID `json:"id"`
|
||
ConversationID ID `json:"conversationId"`
|
||
RunID ID `json:"runId,omitempty"`
|
||
Role Role `json:"role"`
|
||
Parts []Part `json:"parts"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
}
|
||
|
||
// Part 是判别联合:Type 决定哪些字段有意义;未用字段为零值。
|
||
type Part struct {
|
||
Type PartType `json:"type"`
|
||
|
||
Text string `json:"text,omitempty"` // text / thinking(流式增量聚合后)
|
||
|
||
ToolCall *ToolCallPart `json:"toolCall,omitempty"`
|
||
ToolResult *ToolResultPart `json:"toolResult,omitempty"`
|
||
Artifact *ArtifactRef `json:"artifact,omitempty"`
|
||
Hitl *HITLSummary `json:"hitl,omitempty"`
|
||
Plan *PlanSnapshot `json:"plan,omitempty"`
|
||
Card *CardPart `json:"card,omitempty"`
|
||
Err *ErrorPart `json:"error,omitempty"`
|
||
|
||
// 过程标记:true 的部件在 run 终态后由前端折叠为摘要行(4.2)。
|
||
Process bool `json:"process,omitempty"`
|
||
}
|
||
|
||
type ToolCallPart struct {
|
||
ID string `json:"id"`
|
||
Name string `json:"name"`
|
||
Arguments string `json:"arguments,omitempty"` // 原始 JSON
|
||
Duration float64 `json:"durationMs,omitempty"`
|
||
}
|
||
|
||
type ToolResultPart struct {
|
||
CallID string `json:"callId"`
|
||
Status string `json:"status"` // ok | error
|
||
Summary string `json:"summary,omitempty"`
|
||
Truncated bool `json:"truncated,omitempty"` // 超长截断并转工件引用(4.10)
|
||
}
|
||
|
||
type ArtifactRef struct {
|
||
ArtifactID ID `json:"artifactId"`
|
||
Name string `json:"name"`
|
||
Kind string `json:"kind,omitempty"` // document | image | data | ...
|
||
}
|
||
|
||
type HITLSummary struct {
|
||
CardID ID `json:"cardId"`
|
||
Question string `json:"question"`
|
||
Resolved bool `json:"resolved"`
|
||
Answer string `json:"answer,omitempty"` // 选中项 label 或回填文本
|
||
}
|
||
|
||
type ErrorPart struct {
|
||
Code string `json:"code"`
|
||
Message string `json:"message"`
|
||
}
|
||
|
||
// CardPart.Data 是 UI schema 节点(4.6 有限词汇)。
|
||
// CardID 非空 = 收件箱 ActivityCard 的引用部件(如 submit_card 产卡:卡片为产物
|
||
// 权威载体,消息只存引用+锚点渲染);空 = 插件内嵌卡片部件(自包含 Data)。
|
||
type CardPart struct {
|
||
Kind string `json:"kind"`
|
||
Data []UINode `json:"data"`
|
||
CardID ID `json:"cardId,omitempty"`
|
||
}
|
||
|
||
// ---- Run(一切运行皆 Run)----
|
||
|
||
type RunKind string
|
||
|
||
const (
|
||
RunConversation RunKind = "conversation"
|
||
RunSubagent RunKind = "subagent"
|
||
RunTool RunKind = "tool"
|
||
)
|
||
|
||
type RunStatus string
|
||
|
||
const (
|
||
RunPending RunStatus = "pending"
|
||
RunRunning RunStatus = "running"
|
||
RunWaitingHITL RunStatus = "waiting_hitl"
|
||
RunCompleted RunStatus = "completed"
|
||
RunFailed RunStatus = "failed"
|
||
RunCancelled RunStatus = "cancelled"
|
||
RunInterrupted RunStatus = "interrupted"
|
||
)
|
||
|
||
type RunPhase string
|
||
|
||
const (
|
||
PhaseThinking RunPhase = "thinking"
|
||
PhaseActing RunPhase = "acting"
|
||
PhaseResponding RunPhase = "responding"
|
||
PhaseDone RunPhase = "done"
|
||
)
|
||
|
||
type Run struct {
|
||
ID ID `json:"id"`
|
||
ParentRunID ID `json:"parentRunId,omitempty"`
|
||
ConversationID ID `json:"conversationId"`
|
||
ProjectID ID `json:"projectId"`
|
||
Owner ID `json:"owner,omitempty"` // 冗余自会话
|
||
Kind RunKind `json:"kind"`
|
||
ProfileID ID `json:"profileId,omitempty"`
|
||
Status RunStatus `json:"status"`
|
||
Phase RunPhase `json:"phase,omitempty"`
|
||
AgentName string `json:"agentName,omitempty"` // subagent 显示名
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
EndedAt *time.Time `json:"endedAt,omitempty"`
|
||
Usage *Usage `json:"usage,omitempty"`
|
||
Error *ErrorPart `json:"error,omitempty"`
|
||
}
|
||
|
||
type Usage struct {
|
||
PromptTokens int `json:"promptTokens"`
|
||
CompletionTokens int `json:"completionTokens"`
|
||
TotalTokens int `json:"totalTokens"`
|
||
DurationMs float64 `json:"durationMs"`
|
||
ToolCalls int `json:"toolCalls"`
|
||
}
|
||
|
||
// ---- 工件 ----
|
||
|
||
type Artifact struct {
|
||
ID ID `json:"id"`
|
||
ProjectID ID `json:"projectId"`
|
||
Owner ID `json:"owner,omitempty"` // 冗余自项目
|
||
Name string `json:"name"`
|
||
Kind string `json:"kind"`
|
||
MIME string `json:"mime,omitempty"`
|
||
Size int64 `json:"size"`
|
||
SourceRun ID `json:"sourceRun,omitempty"`
|
||
CreatedAt time.Time `json:"createdAt"`
|
||
UpdatedAt time.Time `json:"updatedAt"`
|
||
}
|
||
|
||
// ---- 计划与待办(右栏 Plan / Todos)----
|
||
|
||
type PlanSnapshot struct {
|
||
PlanID ID `json:"planId"`
|
||
Title string `json:"title"`
|
||
Steps []PlanStep `json:"steps"`
|
||
}
|
||
|
||
type PlanStep struct {
|
||
ID string `json:"id"`
|
||
Text string `json:"text"`
|
||
Status string `json:"status"` // pending | in_progress | done | skipped
|
||
AgentRun ID `json:"agentRun,omitempty"`
|
||
}
|
||
|
||
type TodoList struct {
|
||
ConversationID ID `json:"conversationId"`
|
||
Items []TodoItem `json:"items"`
|
||
}
|
||
|
||
type TodoItem struct {
|
||
ID string `json:"id"`
|
||
Text string `json:"text"`
|
||
Status string `json:"status"` // pending | in_progress | done
|
||
}
|