DSH / Atlas
2026-09-06implementedarchitecture

Canonical V3 Session event envelopes

规范的 V3 Session 事件信封

A Session event can cross in-memory, durable, and browser-wire readers. If its type permits missing placement or unrelated surface metadata, a reader can silently omit a message or disagree about which fields affect reconstruction. Multiple spellings for replacement endpoints and empty request-header optionals also allow different stored records to describe the same request. Contradictory tool failure metadata can ma

English

Problem

A Session event can cross in-memory, durable, and browser-wire readers. If its type permits missing placement or unrelated surface metadata, a reader can silently omit a message or disagree about which fields affect reconstruction. Multiple spellings for replacement endpoints and empty request-header optionals also allow different stored records to describe the same request. Contradictory tool failure metadata can make model history and diagnostics report different outcomes.

Decision

Session format V3 uses one canonical event envelope. Every system/message, user/message, assistant/message, and tool/result requires surfaceOp. Known log-only events permit only type, seq, time, data, and optional ignorable: true; their TypeScript variants declare both surface metadata fields as optional never. Native unknown or obsolete ignorable envelopes remain opaque, including their metadata. Assistant messages embed their exact provider stream and alone forbid sourceEventSeqs. System, user, and tool messages may cite a non-empty, unique set of earlier source sequences.

SurfaceOp is exactly 'append' or { op: 'replace', startSeq, endSeq }, with SessionSeq endpoints and no aliases or extra keys. Both endpoints precede the replacing event and identify an inclusive span in current surface order, not numeric sequence order. Session acceptance additionally verifies current membership, ordered endpoints, complete cited coverage, and content-only single-node tool-result replacement. Compaction payload fields such as shadowedRange.start/end and fold-result fields retain their own names; this is not a recursive payload rename.

Current acceptance rejects every request/header.header.system and exactly empty tools: [] or adapterDefaults: {}. System prompts belong to system/message; request/header remains the non-history request snapshot. Writers omit the two empty optionals. Whitespace-only system content, config.stop: [], nested header/source/data extras, and nested tool schema values remain intact. A tool/result with data.error requires message.isError === true; a failed result need not carry error identity. Neither current reads nor migration infer an error outcome from contradictory metadata.

Validation ownership

Core Session owns event-local placement, header-empty-field, and tool-error rules, while its surface manager owns relationships that need the event log. Seed, append, and restoration apply these rules before accepting events. They do not create a general schema for plugin-owned payloads or eagerly expand embedded provider streams.

The generic Gateway client returns raw outputs without validating them. The existing SessionEventStream therefore checks follow snapshots, live durable entries, and history pages before publishing them. Its private wire-event checker validates the exact envelope and delegates event-local rules to the browser-safe core validators. It does not add a generic Gateway schema or validate unrelated plugin payloads. Surface membership and source existence remain Host-owned because a browser window may omit earlier events.

Released V2 to V3 conversion

The V2-to-V3 specification owns the complete historical conversion, its canonicalization rules, and native admission and recovery. Keeping these rules together prevents a cardinality-preserving canonicalization step from being mistaken for an identity migration. Frozen relationship validation uses private views rather than runtime aliases; the original V3 artifact remains authoritative.

Alternatives considered

Default missing placement to append. This invents a model-history decision absent from the stored record and admits invalid V2 artifacts. Required placement keeps all readers accountable to the same evidence.

Accept both replacement spellings in current readers. This preserves two durable representations and makes validation depend on which reader receives them. Only the adjacent edge interprets released keys; current readers accept V3 keys exclusively.

Normalize all empty values or repair tool outcomes. Empty stop lists, whitespace, and plugin payloads can be meaningful. Removing them or setting isError from diagnostics changes recorded facts. The edge performs only named, semantics-preserving conversions and refuses contradictions.

Copy historical validators or pass V3 events directly to them. Copying duplicates relationship semantics; direct reuse would accept obsolete envelope spellings and misinterpret system nodes and repair identities. Strict V3 validation followed by composed private views reuses frozen relationships without widening current acceptance.

Consequences

Typed events, persistence, and browser history agree on required placement and event-local failure semantics. Malformed records fail before projection rather than disappearing from model history. Migration gives up best-effort recovery of contradictory records; retained source generations remain untouched under the released-format publication policy.

This decision partially supersedes envelope representation details in the session surface and reconstructable requests notes. They remain active for ordered projection and logged request ownership. The system-prompt surface-node decision retains prompt ownership, protected-head semantics, and migration rationale. The V2 embedded-stream decision remains active for attempt settlement, exact stream evidence, and cardinality-changing migration; V3 preserves those decisions.

Verification

Core acceptance tests pin invalid seed/append/restore records, typed surface variants, optional failure identity, and unchanged derived state after rejection. Browser transport tests exercise strict follow/page admission before publication. Migration tests cover conversion and restoration; frozen adjacent-edge suites preserve historical semantics. Required coverage also includes codec admission, whitespace and empty stop-list preservation, opaque payload retention, and numerically descending replacement endpoints in valid surface order.

中文

问题

一个 Session 事件会经过内存、持久化与浏览器协议读取器。如果其类型允许缺少位置声明或携带无关 surface 元数据,读取器就可能静默遗漏消息,或对哪些字段影响重建产生分歧。替换端点的多种拼写与空请求头可选字段,也使不同存储记录能够描述同一请求。相互矛盾的工具失败元数据会让模型历史与诊断报告不同结果。

决策

Session 格式 V3 使用一种规范事件信封。每个 system/message、user/message、assistant/message 与 tool/result 都要求 surfaceOp。已知仅日志事件仅允许 type、seq、time、data 与可选的 ignorable: true;其 TypeScript 变体将两个 surface 元数据字段声明为可选 never。原生未知或已退役的可忽略信封(包括其元数据)保持不透明。assistant 消息嵌入精确提供方 stream,且只有此类消息禁止 sourceEventSeqs。system、user 与 tool 消息可以引用非空、唯一的较早来源序号集合。

SurfaceOp 恰好为 'append' 或 { op: 'replace', startSeq, endSeq },端点使用 SessionSeq,不接受别名或额外键。两个端点都早于替换事件,并按当前 surface 顺序而非数值序号顺序标识闭区间。Session 接纳还验证当前成员关系、端点顺序、完整引用覆盖与仅修改内容的单节点工具结果替换。shadowedRange.start/end 等压缩(compaction)载荷字段与折叠结果字段保留各自名称;这不是对载荷进行递归重命名。

当前接纳拒绝任何 request/header.header.system 以及恰好为空的 tools: [] 或 adapterDefaults: {}。系统提示词属于 system/message;request/header 仍是请求非历史状态的快照。写入方省略两个空可选字段。仅含空白的系统内容、config.stop: []、嵌套 header/source/data 扩展与嵌套工具 schema 值保持原样。带有 data.error 的 tool/result 要求 message.isError === true;失败结果不必携带错误身份。当前读取与迁移均不会根据矛盾元数据推断错误结果。

校验所有权

核心 Session负责事件本地的位置、请求头空字段与工具错误规则,其 surface 管理器负责需要事件日志的关系。seed、append 与恢复会在接纳事件前应用这些规则。它们不会为插件自有载荷创建通用 schema,也不会提前展开嵌入式提供方 stream。

通用 Gateway 客户端返回未经校验的原始输出。因此,现有 SessionEventStream 会在发布前检查 follow 快照、实时持久条目与历史页。其私有协议事件检查器验证精确信封,并将事件本地规则委托给可在浏览器中使用的核心校验器。它不添加通用 Gateway schema,也不校验无关插件载荷。surface 成员关系与来源是否存在仍由 Host 负责,因为浏览器窗口可能未包含较早事件。

已发布 V2 到 V3 的转换

V2 到 V3 规范负责完整历史转换、规范化规则及原生准入与恢复。将这些规则集中在一起,可以避免把保持事件数量的规范化步骤误认为恒等迁移。冻结的关系校验使用私有视图而非运行时别名;原始 V3 产物仍具权威性。

曾考虑的替代方案

将缺失的位置默认为 append。 这会凭空添加存储记录中不存在的模型历史决策,并接纳无效 V2 产物。要求位置声明,使所有读取器必须依据同一证据。

当前读取器接受两种替换拼写。 这会保留两种持久表示,并使校验取决于接收记录的读取器。只有相邻迁移边解释已发布的键;当前读取器只接受 V3 键。

规范化所有空值或修复工具结果。 空 stop 列表、空白与插件载荷可能有意义。删除它们或根据诊断设置 isError 会改变已记录事实。迁移边只执行具名且保持语义的转换,并拒绝矛盾。

复制历史校验器或直接向其传入 V3 事件。 复制会重复关系语义;直接复用则会接受旧信封拼写,并误解系统节点与修复身份。严格的 V3 校验加组合后的私有视图,可以在不扩大当前接纳范围的前提下复用冻结关系。

后果

类型化事件、持久化与浏览器历史对必填位置和事件本地失败语义保持一致。畸形记录在投影前失败,而不会从模型历史中消失。迁移放弃对矛盾记录的尽力恢复;已发布格式的发布策略保证保留的源代次不被修改。

本决策部分取代会话 surface与可重建请求说明中的信封表示细节。它们继续负责有序投影与已记录请求的所有权。系统提示词 surface 节点决策保留提示所有权、受保护头节点语义与迁移依据。V2 嵌入式 stream 决策继续负责尝试结算、精确 stream 证据与改变事件数量的迁移;V3 保留这些决策。

验证

核心接纳测试固定无效 seed/append/restore 记录、类型化 surface 变体、可选失败身份与拒绝后派生状态不变。浏览器传输测试检验发布前的严格 follow/page 接纳。迁移测试覆盖转换与恢复;冻结的相邻迁移边测试保留历史语义。必需覆盖还包括编解码器接纳、空白与空 stop 列表保留、不透明载荷保留,以及按合法 surface 顺序排列但数值递减的替换端点。