// Package core 定义 Agent-System 的核心契约:领域模型、流式事件、HITL 卡片、 // 插件 API、设置与 UI 词汇。本仓只含契约与少量纯函数,不含实现、不含 I/O。 // // JSON 标签(camelCase)是前后端与插件共同的线格式契约;TS 类型镜像见 ts/types.ts, // 黄金样本见 testdata/golden/(conformance 测试保证 Go 序列化与样本一致)。 package core import "time" // ---- 标识 ---- // ID 形态为 _;生成由后端负责,契约只约束非空与唯一。 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"` // 跨会话入站:私有会话,不被他读、不出现在他方列表 // PermissionMode 是会话权限:空或 default 沿用画像;plan 只读加计划工具;auto_edit 放行工作区写文件。 PermissionMode string `json:"permissionMode,omitempty"` // SessionNote 是本会话要求,组装时附在上下文末尾,不进入系统前缀。 SessionNote string `json:"sessionNote,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) PartCheck PartType = "check" // 终轮自动检查,过程区一行,不是给用户的回复 ) 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"` // Excluded 为真时界面仍显示,但组装上下文时整条(及同一 run 的成组消息)不送入模型。 Excluded bool `json:"excluded,omitempty"` // VariantGroup 把同一轮的候选回复绑在一起。只把未排除的那条送入模型。 VariantGroup string `json:"variantGroup,omitempty"` VariantIndex int `json:"variantIndex,omitempty"` } // 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"` Check *CheckPart `json:"check,omitempty"` // 过程标记:true 的部件在 run 终态后由前端折叠为摘要行(4.2)。 Process bool `json:"process,omitempty"` // DurationMs 是 thinking 部件的思考时长(毫秒,从首个推理增量到最后一个)。 // 工具耗时在 ToolCallPart.Duration,不复用本字段。 DurationMs float64 `json:"durationMs,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"` } // CheckPart 是终轮自动检查的结果。过程区显示一行,不进入给用户的回复。 type CheckPart struct { Passed bool `json:"passed"` Reason string `json:"reason,omitempty"` } // 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" PhaseFinalizing RunPhase = "finalizing" // 工作循环已结束,正在整理给用户的最终回复 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"` // 以下四项是 N3 的计费拆分(additive;旧记录为零值省略): // Last* 是最近一次请求的用量(上一请求),Cache* 是缓存命中累计。 LastPromptTokens int `json:"lastPromptTokens,omitempty"` LastCompletionTokens int `json:"lastCompletionTokens,omitempty"` CacheReadTokens int `json:"cacheReadTokens,omitempty"` CacheWriteTokens int `json:"cacheWriteTokens,omitempty"` // Model 是实际给出这段用量的模型。空表示当时没有记录。 Model string `json:"model,omitempty"` } // ---- 工件 ---- 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 }