Files
Agent-System-Core/events.go
weichen bd632236c2 Extend messages and context observation for variants and estimates
Why: Labeled secrets, excluded turns, and candidate replies need fields on the shared message contract, and context snapshots need a section breakdown plus a stable prefix hash.
Evidence: go test ./... in agent-system-core. New fields use omitempty, so existing golden JSON stays the same.
Impact: Clients that ignore unknown fields keep working. Assemblers can now mark a message excluded or as one candidate in a group.
Refs: docs/records/2026-10-04-sillytavern-review.md
2026-10-04 18:18:57 +00:00

214 lines
7.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package core
import (
"encoding/json"
"strings"
)
// 事件信封:后端 → 前端的唯一增量通道(SSE),持久化后转发,Seq 在会话内单调。
// 消费方对未知 Type 静默忽略(原则 6 前向兼容)。
// 项目流(D50):项目频道事件以伪会话键 "project:<projectId>" 复用同一机制
// (独立 seq、持久化、断线重放),信封以 ProjectID 标识归属(会话流事件为空)。
type StreamEvent struct {
Seq int64 `json:"seq"`
RunID ID `json:"runId,omitempty"`
ConversationID ID `json:"conversationId"`
ProjectID ID `json:"projectID,omitempty"` // 项目流事件的项目归属(D50;只增不删)
TS string `json:"ts"` // RFC3339
V int `json:"v"`
Type StreamEventType `json:"type"`
Payload json.RawMessage `json:"payload,omitempty"`
}
type StreamEventType string
// 项目流频道约定(D50):项目频道以伪会话键 "project:<projectId>" 复用会话
// 事件的持久化/seq/重放机制;信封 ProjectID 由该键派生(发布与重放同源)。
const projectChannelPrefix = "project:"
// ProjectChannelKey 返回项目流的事件频道键。
func ProjectChannelKey(projectID ID) ID { return ID(projectChannelPrefix + string(projectID)) }
// ProjectFromChannel 反解项目流频道键;非项目流频道返回 false。
func ProjectFromChannel(key ID) (ID, bool) {
pid, ok := strings.CutPrefix(string(key), projectChannelPrefix)
return ID(pid), ok && pid != ""
}
const (
EvMessageDelta StreamEventType = "message.delta"
EvThinkingDelta StreamEventType = "thinking.delta"
EvToolCallDelta StreamEventType = "tool.call.delta" // 参数增量:工具开始执行前即可上屏
EvToolCall StreamEventType = "tool.call"
EvToolOutput StreamEventType = "tool.output" // 执行中的 stdout/stderr 增量
EvToolResult StreamEventType = "tool.result"
EvRunPhase StreamEventType = "run.phase"
EvRunCheck StreamEventType = "run.check" // 终轮自动检查,过程区一行
EvHITLRequest StreamEventType = "hitl.request"
EvHITLResolved StreamEventType = "hitl.resolved"
EvPlanUpdate StreamEventType = "plan.update"
EvTodoUpdate StreamEventType = "todo.update"
EvAgentSpawn StreamEventType = "agent.spawn"
EvAgentProgress StreamEventType = "agent.progress"
EvAgentResult StreamEventType = "agent.result"
EvArtifactCreated StreamEventType = "artifact.created"
EvArtifactUpdated StreamEventType = "artifact.updated"
EvRunCompleted StreamEventType = "run.completed"
EvRunFailed StreamEventType = "run.failed"
EvError StreamEventType = "error"
// 收件箱卡片(activity.go):前端右栏收件箱的唯一数据源(投影语义,服务端权威)。
EvCardCreated StreamEventType = "card.created"
EvCardUpdated StreamEventType = "card.updated"
EvCardStatus StreamEventType = "card.status"
EvCardResolved StreamEventType = "card.resolved"
)
// ProtocolVersion 是事件信封与 payload 词汇的当前版本。
const ProtocolVersion = 1
// ---- 各事件 payload(新增字段只增不删;消费方忽略未知字段)----
// MessageDeltaPayload:正文增量。Index 标识目标 Part 序号(流式聚合用)。
type MessageDeltaPayload struct {
Index int `json:"index"`
Text string `json:"text"`
}
type ThinkingDeltaPayload struct {
Index int `json:"index"`
Text string `json:"text"`
}
type ToolCallPayload struct {
CallID string `json:"callId"`
Name string `json:"name"`
Arguments string `json:"arguments,omitempty"`
}
// ToolCallDeltaPayload 是模型正在编写的工具参数增量。Index 标识同轮第几次调用
// (与供应商 tool_calls 下标一致);Name/CallID 往往只在首个分片出现。
type ToolCallDeltaPayload struct {
Index int `json:"index"`
CallID string `json:"callId,omitempty"`
Name string `json:"name,omitempty"`
Delta string `json:"delta"`
}
// ToolOutputPayload 是工具执行过程中的输出增量。Stream 为 stdout 或 stderr。
type ToolOutputPayload struct {
CallID string `json:"callId"`
Stream string `json:"stream"`
Text string `json:"text"`
}
type ToolResultPayload struct {
CallID string `json:"callId"`
Status string `json:"status"`
Summary string `json:"summary,omitempty"`
Truncated bool `json:"truncated,omitempty"`
DurationMs float64 `json:"durationMs,omitempty"`
}
type RunPhasePayload struct {
Phase RunPhase `json:"phase"`
}
// RunCheckPayload 与 CheckPart 同形,让运行中和重新加载后的检查行一致。
type RunCheckPayload struct {
Passed bool `json:"passed"`
Reason string `json:"reason,omitempty"`
}
type HITLResolvedPayload struct {
CardID ID `json:"cardId"`
Answer string `json:"answer,omitempty"`
Kind string `json:"kind"` // choice | free | timeout | cancelled
}
type PlanUpdatePayload struct {
Plan PlanSnapshot `json:"plan"`
}
type TodoUpdatePayload struct {
List TodoList `json:"list"`
}
// AgentSpawnPayload:子代理派生;AgentRun 即子 Run(父子关系即任务树)。
type AgentSpawnPayload struct {
AgentRun ID `json:"agentRun"`
Name string `json:"name"`
Task string `json:"task"`
}
type AgentProgressPayload struct {
AgentRun ID `json:"agentRun"`
Note string `json:"note,omitempty"`
Phase RunPhase `json:"phase,omitempty"`
}
type AgentResultPayload struct {
AgentRun ID `json:"agentRun"`
Status RunStatus `json:"status"`
Summary string `json:"summary,omitempty"`
// Text 为子代理完整文本产出(squad 步骤交付物用;截断摘要见 Summary)。
Text string `json:"text,omitempty"`
}
type ArtifactPayload struct {
Artifact Artifact `json:"artifact"`
}
type RunCompletedPayload struct {
Usage Usage `json:"usage"`
// Context 为该次运行的上下文组装观测(4.10/4.17:构成 + 裁剪记录;可解释性)。
Context *ContextObservation `json:"context,omitempty"`
}
// ContextSection 是组装结果里一段的估算。EstTokens 用 UTF-8 字节数 / 3.35,
// 再按上一请求的真实用量校准。
type ContextSection struct {
Name string `json:"name"`
EstTokens int `json:"estTokens"`
}
// ContextObservation 记录一次模型输入的实际构成与预算裁剪(ctxasm 产出)。
type ContextObservation struct {
Items []string `json:"items"` // 如 system(画像) / history(12) / attachments(1) / knowledge(3)
Truncations []string `json:"truncations,omitempty"` // 裁剪记录(历史超窗/工具结果超限/附件截断)
EstChars int `json:"estChars"` // 估算输入量(token;字段名保持兼容)
Sections []ContextSection `json:"sections,omitempty"`
PrefixHash string `json:"prefixHash,omitempty"` // 系统前缀哈希,前缀不变时保持稳定
}
type RunFailedPayload struct {
Code string `json:"code"`
Message string `json:"message"`
}
type ErrorPayload struct {
Code string `json:"code"`
Message string `json:"message"`
RunID ID `json:"runId,omitempty"`
}
// CardPayload:card.created / card.updated 携带整卡投影(服务端权威,前端整体替换)。
type CardPayload struct {
Card ActivityCard `json:"card"`
}
// CardStatusPayload:card.status 携带状态迁移(含 Tone,便于轻量更新状态灯)。
type CardStatusPayload struct {
CardID ID `json:"cardId"`
Status CardStatus `json:"status"`
Tone string `json:"tone,omitempty"`
Note string `json:"note,omitempty"`
}
// CardResolvedPayload:card.resolved 携带所点动作语义——确认结论回写对话时间线
// (AI 回执)并写入审计;Answer 为自由输入文本(如有)。
type CardResolvedPayload struct {
CardID ID `json:"cardId"`
ActionID string `json:"actionId,omitempty"`
Answer string `json:"answer,omitempty"`
}