@deepseek-ai/dsh-session 0.1.2-rc.1 → 0.1.5-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/core/session/README.md
5
- README.md: f5cf910854203021a619cc786dfd13705927ffc1
6
- README.zh.md: 385d7fd63a6e4dec9c23c9d38a352942d7dbc7f9
5
+ README.md: a06b22b5e8f48743047c68e883edd496fbc6eb77
6
+ README.zh.md: 755894b4c30f0a3807f472cece32685d102efbeb
package/README.md CHANGED
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- `dsh-session` provides the append-only session log that records an agent's whole interaction history — the single source of truth every model-visible fact flows through. The LLM message history is *derived* from the log (`deriveMessages()`), never stored separately, so replay is re-derivation from the same events and compaction can shadow older surface entries without deleting history. The package also provides the in-memory store (`ctx.sessions`), the typed `SessionEvent` vocabulary that plugins extend by declaration merging, and the surface layer that orders message-producing events. Persistence is deliberately a separate concern: backends subscribe to `session/event` and flush on `session/flush`. Choose it as the foundation of any agent session; it runs no model calls itself.
12
+ `dsh-session` records every model-visible fact in an append-only session log and derives model history from that record. Consumers can inspect, replay, fork, and flush sessions while preserving historical events; compaction hides superseded entries from the active conversation without deleting them. Sessions remain in memory unless a persistence backend is added, and durability checkpoints wait for configured backends. Choose this package wherever an agent needs a reconstructable session record; it does not call models.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -47,7 +47,11 @@ session.append('user/message', { role: 'user', content: [{ type: 'text', text: '
47
47
  session.deriveMessages() // the derived model history
48
48
  ```
49
49
 
50
- Surface events (`user/message`, `assistant/message`, `tool/result`) must declare how they join the ordered surface; raw chunks, boundaries, and other log-only events never produce a message.
50
+ Surface events (`system/message`, `user/message`, `assistant/message`, `tool/result`) require `surfaceOp` in both typed events and append input. A replacement uses exactly `{ op: 'replace', startSeq, endSeq }`, with inclusive `SessionSeq` endpoints in current surface order. An Assistant message embeds its exact compact provider stream and forbids `sourceEventSeqs`. Known log-only events forbid both metadata fields and never produce a message.
51
+
52
+ Append, seed/restore, and event adoption/snapshot reject any `header.system` and exactly empty optional request-header fields (`tools: []`, `adapterDefaults: {}`) instead of normalizing input. Tool-result `data.error` is allowed only when `message.content[0].isError === true`; failure identity remains optional. Rejected appends do not change the log, derived state, or event feed. Adoption validates event-local metadata but not referenced history or replacement membership.
53
+
54
+ `system/message` holds the rendered system prompt: the first one is surface node 0, the prepared call capability governs admission, with a non-empty rendering consolidated at the first system node on an incapable route or appended after cached history inside a continuing `in-history` series; empty system nodes project to no message, so clearing the prompt requires logged empty replacements of all active system nodes, not just the latest; the surface fold rejects a replacement covering node 0 while it is a `system/message` unless the replacing event is itself a `system/message` over exactly that node, while later system nodes carry no protection and a compaction range may shadow them ([decision](../../../.agents/notes/implemented/architecture/2026-09-02-system-prompt-as-surface-node.md)).
51
55
 
52
56
  ### Read the log
53
57
 
@@ -77,7 +81,7 @@ This section explains how the package realizes the behavior above; the observabl
77
81
 
78
82
  ### Design concept
79
83
 
80
- The package is built on event sourcing: a `Session` is an append-only log of typed `SessionEvent`s, and everything else — model history, transcripts, telemetry, titles, persistence — derives from that stream. The surface is a derived projection: an incremental manager validates append candidates, advances the ordered view from committed events, and tracks a `replaceGeneration` that bumps on every committed rewrite. Model-visible means logged: anything that reaches a model request must be reconstructable from the log. The shared [row codec](src/chunk-rows.ts) losslessly converts event sequences to compact rows and back, preserves unrecognized events verbatim, and rejects malformed rows. Persistence backends decide whether to pack writes; bounded history transports can use the same rows while retaining the complete logical interval and exact decoding for consumers that need token boundaries.
84
+ The package is built on event sourcing: a `Session` is an append-only log of typed `SessionEvent`s, and everything else — model history, transcripts, telemetry, titles, persistence — derives from that stream. The surface is a derived projection: an incremental manager validates append candidates, advances the ordered view from committed events, and tracks a `replaceGeneration` that bumps on every committed rewrite. Model-visible means logged: anything that reaches a model request must be reconstructable from the log. Each model attempt that reaches settlement commits one event: `assistant/message` carries the assembled model-visible message plus its compact timed stream, while `assistant/attempt` retains a failed, retried, cancelled, or stream-error attempt without adding model history. A hard process loss before settlement leaves no durable attempt stream.
81
85
 
82
86
  ### Request headers
83
87
 
@@ -92,7 +96,6 @@ The package is built on event sourcing: a `Session` is an append-only log of typ
92
96
  | [`src/surface.ts`](src/surface.ts) | Ordered surface projection, replacement validation, `deriveEventMessage` |
93
97
  | [`src/request-header.ts`](src/request-header.ts) | `request/header` folding and reconstruction |
94
98
  | [`dsh-util-values`](../../util/values/README.md) | Shared lossless JSON validation and detached snapshots |
95
- | [`src/chunk-rows.ts`](src/chunk-rows.ts) | Shared compact-row storage codec for persistence backends |
96
99
  | [`src/repair.ts`](src/repair.ts) | Cold repair of crash-orphaned logs |
97
100
  | [`src/invariant.ts`](src/invariant.ts) | Invariant companion: seq, turn/step enclosure, tool call/result pairing |
98
101
 
@@ -102,11 +105,11 @@ Every append uses the shared iterative `snapshotJsonValue()` pass, which reads,
102
105
 
103
106
  ### Derived history
104
107
 
105
- `deriveMessages()` caches each surface node's projection once and returns a fresh array per call over shared, deep-frozen messages; each of the three surface event types (`user/message`, `assistant/message`, `tool/result`) projects its own message kind — user content verbatim, the assembled assistant message with its provider and model, or a user-role tool result. A surface rewrite rebuilds the projection — there is no raw-log fallback, so the surface is the single source of derived history.
108
+ `deriveMessages()` caches each surface node's projection once and returns a fresh array per call over shared, deep-frozen messages; each of the four surface event types (`system/message`, `user/message`, `assistant/message`, `tool/result`) projects its own message kind — the system-role prompt (an empty-content system node projects to no message), user content verbatim, the assembled assistant message with its provider and model, or a user-role tool result. Embedded Assistant streams and `assistant/attempt` events remain replay and diagnostic data only. A surface rewrite rebuilds the projection — there is no raw-log fallback, so the surface is the single source of derived history.
106
109
 
107
110
  ### The request header
108
111
 
109
- The loop logs a full canonical `request/header` snapshot (call config, adapter defaults, rendered system prompt, assembled tool schemas) at each loop-instance boundary and on change; `foldRequestHeader(events)` reconstructs it by selecting the latest snapshot, making every conversation request a pure function of the log. Route metadata (`request/context`) is separate logged state appended only when the provider, model, or capacity differs.
112
+ The loop logs a full canonical `request/header` snapshot (call config, adapter defaults, assembled tool schemas — the rendered system prompt is a `system/message` surface node, not header state) at each loop-instance boundary and on change; `foldRequestHeader(events)` reconstructs it by selecting the latest snapshot, making every conversation request a pure function of the log. Route metadata (`request/context`) is separate logged state appended only when the provider, model, capacity, or `systemPromptUpdate` mode differs; it records the actual prepared call's mode after prompt and user admission, rather than supplying that admission decision.
110
113
 
111
114
  </details>
112
115
 
@@ -132,7 +135,7 @@ The package-level contract is enough for most consumers; read these when you nee
132
135
 
133
136
  #### What the model sees
134
137
 
135
- The model receives the complete messages from `user/message`, `assistant/message`, and `tool/result` surface entries verbatim — identities, roles, sources, and content blocks are the same values established at creation, and projections never mint identities. Direct prompts and injected context remain separate `user/message` events whose sources preserve their provenance. Chunks, boundaries, usage, and other log-only events add no message.
138
+ The model receives the complete messages from `system/message`, `user/message`, `assistant/message`, and `tool/result` surface entries verbatim, the system prompt first — identities, roles, sources, and content blocks are the same values established at creation, and projections never mint identities. Direct prompts and injected context remain separate `user/message` events whose sources preserve their provenance. Embedded streams, `assistant/attempt`, boundaries, and other log-only facts add no message.
136
139
 
137
140
  #### Token effect
138
141
 
@@ -160,15 +163,15 @@ Append-only; newly visible content follows the reusable request prefix and does
160
163
 
161
164
  #### What the model sees
162
165
 
163
- The session reconstructs the system prompt, tool schemas, call config, and session prefix that the loop actually sent. Header events do not add a second copy to message history; the prefix is prepended outside `deriveMessages()`.
166
+ The session reconstructs the tool schemas and call config that the loop actually sent; the system prompt is part of `deriveMessages()` as surface node 0 and, after an in-history update, as the latest system node. Header events add no message to history and hold no copy of the prompt.
164
167
 
165
168
  #### Token effect
166
169
 
167
- Zero duplicate tokens from logging. The reconstructed prefix, system text, and schemas still incur their normal per-request cost.
170
+ Zero duplicate tokens from logging. The system nodes and schemas still incur their normal per-request cost.
168
171
 
169
172
  #### KV Cache effect
170
173
 
171
- Logging causes no invalidation, and exact reconstruction preserves request-prefix identity. A later header with changed prefix, prompt, or schemas may invalidate reuse from its first difference.
174
+ Logging causes no invalidation, and exact reconstruction preserves request-prefix identity. A later header with changed config or schemas may invalidate reuse from its first difference; a prompt change that replaces surface node 0 invalidates reuse from the first token, while an in-history append keeps the prefix through the cached history reusable.
172
175
 
173
176
  ## Known Limitations and Deferred Work
174
177
 
@@ -177,8 +180,8 @@ Logging causes no invalidation, and exact reconstruction preserves request-prefi
177
180
 
178
181
  These limits define when the session store needs special care. They are current package constraints, not a task backlog.
179
182
 
180
- - **`fork()` cuts only at stable boundaries of live sessions** — the selected prefix must end outside an open turn and the source must be in the store; forking a persisted-but-unloaded session is excluded from the [fork API](../../../.agents/notes/implemented/feature/2026-06-30-session-store-fork-api.md).
181
- - **`SESSION_FORMAT_VERSION` stays pinned at `0`**pre-release, no broad compatibility implied: `Session` accepts only current seed shapes, a backend refuses any other version, and unknown event types refuse reconstruction unless marked `ignorable` in the envelope ([mechanism](../../../.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.md)).
183
+ - **`fork()` cuts only at stable boundaries of live sessions** — the selected prefix must end outside an open turn and the source must be in the store; forking a persisted-but-unloaded session is excluded from the fork API.
184
+ - **`SESSION_FORMAT_VERSION` names the current V3 logical representation** the V3 reader rejects retired `header.system` and validates `system/message` payloads and protected-head rewrites. Historical headers and events belong to adjacent format packages; the V2→V3 edge converts supported history before constructing `Session`, and write open publishes only the V3 successor. Equal-version unknown events require the envelope's explicit `ignorable` marker, which does not promise safe structural migration ([mechanism](../../../.agents/notes/implemented/architecture/2026-08-31-released-session-format-migrations.md)).
182
185
  - **`TurnEndReasonMap` omits the ACP-named `refusal` / `max_turn_requests` variants** — producer-gated: they land when an adapter or the loop first emits them.
183
186
  - **No session tree beyond fork** — a pi-style entry tree over branched sessions is deferred unless a consumer needs more than boundary-based forking.
184
187
 
package/README.zh.md CHANGED
@@ -9,7 +9,7 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- `dsh-session` 提供仅追加的会话日志,记录 agent(智能体)的完整交互历史——每个模型可见事实都流经的单一真源。LLM(大语言模型)消息历史由日志*派生*(`deriveMessages()`),从不另行存储,因此回放就是对同一批事件重新派生,压缩(compaction)也可以遮蔽较旧的表层条目而不删除历史。该包还提供内存存储(`ctx.sessions`)、插件通过声明合并扩展的类型化 `SessionEvent` 词汇,以及为产生消息的事件排序的 surface 层。持久化刻意是独立关注点:后端订阅 `session/event` 并在 `session/flush` 时刷新。作为任何 agent 会话的基础时请选择本包;它本身不运行模型调用。
12
+ `dsh-session` 在仅追加的会话日志中记录每个模型可见事实,并从该记录派生模型历史。消费方可以检查、回放、派生和刷新会话,同时保留历史事件;压缩会在活跃对话中隐藏被取代的条目,但不会删除它们。除非添加持久化后端,否则会话仅保留在内存中;持久性检查点会等待配置的后端。agent 需要可重建的会话记录时请选择本包;它本身不调用模型。
13
13
 
14
14
  ## 目录
15
15
 
@@ -47,7 +47,11 @@ session.append('user/message', { role: 'user', content: [{ type: 'text', text: '
47
47
  session.deriveMessages() // the derived model history
48
48
  ```
49
49
 
50
- 表层事件(`user/message`、`assistant/message`、`tool/result`)必须声明如何进入有序 surface;原始分片、边界与其他仅日志事件从不产生消息。
50
+ 表层事件(`system/message`、`user/message`、`assistant/message`、`tool/result`)在类型化事件与追加输入中都必须带有 `surfaceOp`。替换操作仅接受 `{ op: 'replace', startSeq, endSeq }`,端点为包含边界的 `SessionSeq`,按当前 surface 顺序解释。Assistant message 嵌入其精确紧凑 provider stream,并禁止 `sourceEventSeqs`。已知仅日志事件禁止这两个元数据字段,且从不产生消息。
51
+
52
+ 追加、seed/restore 与事件 adoption/snapshot 会拒绝任何 `header.system` 及恰好为空的可选请求头字段(`tools: []`、`adapterDefaults: {}`),而不规范化输入。工具结果的 `data.error` 仅在 `message.content[0].isError === true` 时允许存在;失败标识仍是可选的。被拒绝的追加不会改变日志、派生状态或事件流。Adoption 校验事件局部元数据,但不校验所引用的历史或替换端点是否属于 surface。
53
+
54
+ `system/message` 承载渲染后的系统提示词:第一条是 surface 第 0 号节点,准入依据已准备调用的能力,不具备能力的路由将非空渲染文本归并到首个系统节点,延续中的 `in-history` 序列则在缓存历史之后追加;空系统节点不投影为消息,因此清除提示词必须为所有生效的系统节点记录空内容替换,而非仅替换最新节点;当第 0 号节点是 `system/message` 时,surface 折叠拒绝覆盖它的替换,除非替换事件本身是恰好覆盖该节点的 `system/message`,而后续系统节点不受保护,压缩范围可以遮蔽它们([决策](../../../.agents/notes/implemented/architecture/2026-09-02-system-prompt-as-surface-node.zh.md))。
51
55
 
52
56
  ### 读取日志
53
57
 
@@ -77,7 +81,7 @@ session.deriveMessages() // the derived model history
77
81
 
78
82
  ### 设计理念
79
83
 
80
- 该包建立在事件溯源之上:`Session` 是类型化 `SessionEvent` 的仅追加日志,其他一切——模型历史、transcript、遥测、标题、持久化——都从这条流派生。surface 是派生投影:一个增量管理器校验追加候选、根据已提交事件推进有序视图,并跟踪每次已提交重写都会递增的 `replaceGeneration`。模型可见即已记录:任何到达模型请求的内容都必须能从日志重建。共享的[行编解码器](src/chunk-rows.ts)在事件序列与紧凑行之间无损转换,逐字保留无法识别的事件,并拒绝形态错误的行。持久化后端决定是否打包写入;有界历史传输可以使用同一种行,同时保留完整逻辑区间,并为需要 token 边界的消费方提供精确解码。
84
+ 该包建立在事件溯源之上:`Session` 是类型化 `SessionEvent` 的仅追加日志,其他一切——模型历史、transcript、遥测、标题、持久化——都从这条流派生。surface 是派生投影:一个增量管理器校验追加候选、根据已提交事件推进有序视图,并跟踪每次已提交重写都会递增的 `replaceGeneration`。模型可见即已记录:任何到达模型请求的内容都必须能从日志重建。每个到达 settlement 的模型 attempt 都会提交一个事件:`assistant/message` 携带组装后的模型可见 message 及其紧凑带时间 stream,`assistant/attempt` 则保留失败、重试、取消或 stream error attempt,且不添加模型历史。如果进程在 settlement 前硬中断,则不会留下持久 attempt stream。
81
85
 
82
86
  ### 请求 header
83
87
 
@@ -92,7 +96,6 @@ session.deriveMessages() // the derived model history
92
96
  | [`src/surface.ts`](src/surface.ts) | 有序 surface 投影、替换校验、`deriveEventMessage` |
93
97
  | [`src/request-header.ts`](src/request-header.ts) | `request/header` 折叠与重建 |
94
98
  | [`dsh-util-values`](../../util/values/README.zh.md) | 共享无损 JSON 校验与分离式快照 |
95
- | [`src/chunk-rows.ts`](src/chunk-rows.ts) | 供持久化后端使用的共享紧凑行存储编解码器 |
96
99
  | [`src/repair.ts`](src/repair.ts) | 崩溃遗留日志的冷修复 |
97
100
  | [`src/invariant.ts`](src/invariant.ts) | 不变式配套:序号、轮次/步骤闭合、工具调用/结果配对 |
98
101
 
@@ -102,11 +105,11 @@ session.deriveMessages() // the derived model history
102
105
 
103
106
  ### 派生历史
104
107
 
105
- `deriveMessages()` 把每个 surface 节点的投影缓存一次,每次调用都返回共享、深度冻结消息之上的新数组;三种 surface 事件类型(`user/message`、`assistant/message`、`tool/result`)各自投影自己的消息种类——user 内容原样、带提供方与模型的组装 assistant 消息,或 user 角色的工具结果。surface 重写会重建投影——不存在原始日志回退,因此 surface 是派生历史的唯一来源。
108
+ `deriveMessages()` 把每个 surface 节点的投影缓存一次,每次调用都返回共享、深度冻结消息之上的新数组;四种 surface 事件类型(`system/message`、`user/message`、`assistant/message`、`tool/result`)各自投影自己的消息种类——system 角色的提示词(空内容的系统节点投影为无消息)、user 内容原样、带提供方与模型的组装 assistant 消息,或 user 角色的工具结果。嵌入式 Assistant stream 与 `assistant/attempt` 事件只保留重放和诊断数据。surface 重写会重建投影——不存在原始日志回退,因此 surface 是派生历史的唯一来源。
106
109
 
107
110
  ### 请求头
108
111
 
109
- 循环在每个循环实例边界及变更时记录完整规范 `request/header` 快照(调用配置、适配器默认值、渲染后的系统提示词、组装后的工具 schema);`foldRequestHeader(events)` 通过选择最新快照来重建它,使每个对话请求都成为日志的纯函数。路由元数据(`request/context`)是独立的已记录状态,仅在提供方、模型或容量变化时追加。
112
+ 循环在每个循环实例边界及变更时记录完整规范 `request/header` 快照(调用配置、适配器默认值、组装后的工具 schema——渲染后的系统提示词是 `system/message` surface 节点,不是 header 状态);`foldRequestHeader(events)` 通过选择最新快照来重建它,使每个对话请求都成为日志的纯函数。路由元数据(`request/context`)是独立的已记录状态,仅在提供方、模型、容量或 `systemPromptUpdate` 模式变化时追加;它在提示词与用户消息准入之后记录实际已准备调用的模式,而非提供准入决策。
110
113
 
111
114
  </details>
112
115
 
@@ -132,7 +135,7 @@ session.deriveMessages() // the derived model history
132
135
 
133
136
  #### 模型看到什么
134
137
 
135
- 模型会原样接收 `user/message`、`assistant/message` 与 `tool/result` surface 条目中的完整消息——标识、角色、来源与内容块都与创建时确定的值相同,投影从不生成标识。直接提示词与注入上下文仍是彼此独立的 `user/message` 事件,各事件的来源会保留其出处。分片、边界、用量与其他仅日志事件不会添加消息。
138
+ 模型会原样接收 `system/message`、`user/message`、`assistant/message` 与 `tool/result` surface 条目中的完整消息,系统提示词在先——标识、角色、来源与内容块都与创建时确定的值相同,投影从不生成标识。直接提示词与注入上下文仍是彼此独立的 `user/message` 事件,各事件的来源会保留其出处。嵌入式 stream、`assistant/attempt`、边界与其他仅日志事实不会添加消息。
136
139
 
137
140
  #### Token 影响
138
141
 
@@ -160,15 +163,15 @@ session.deriveMessages() // the derived model history
160
163
 
161
164
  #### 模型看到什么
162
165
 
163
- 会话会重建循环实际发送的系统提示词、工具 schema、调用配置与会话前缀。请求头事件不会向消息历史加入第二份副本;前缀在 `deriveMessages()` 外部前置。
166
+ 会话会重建循环实际发送的工具 schema 与调用配置;系统提示词作为 surface 第 0 号节点、并在历史内更新之后作为最新的系统节点,属于 `deriveMessages()` 的一部分。请求头事件不向历史加入任何消息,也不持有提示词的副本。
164
167
 
165
168
  #### Token 影响
166
169
 
167
- 日志记录不产生重复 token。重建的前缀、系统文本与 schema 仍会产生正常的逐请求开销。
170
+ 日志记录不产生重复 token。各系统节点与 schema 仍会产生正常的逐请求开销。
168
171
 
169
172
  #### KV Cache 影响
170
173
 
171
- 记录日志不会导致失效,精确重建会保持请求前缀一致。后续请求头若更改前缀、提示词或 schema,可能从第一处差异开始使复用失效。
174
+ 记录日志不会导致失效,精确重建会保持请求前缀一致。后续请求头若更改配置或 schema,可能从第一处差异开始使复用失效;替换 surface 第 0 号节点的提示词变更会从第一个 token 起使复用失效,而历史内追加则保持直到已缓存历史末尾的前缀可复用。
172
175
 
173
176
  ## 已知限制与延期工作
174
177
 
@@ -177,8 +180,8 @@ session.deriveMessages() // the derived model history
177
180
 
178
181
  这些限制说明会话存储何时需要特别留意。它们是当前包约束,不是任务积压。
179
182
 
180
- - **`fork()` 仅在实时会话的稳定边界处切分**:所选前缀结束时不得有开放轮次,且源会话必须位于存储中;[fork API](../../../.agents/notes/implemented/feature/2026-06-30-session-store-fork-api.zh.md) 不支持对已持久化但未加载的会话进行 fork。
181
- - **`SESSION_FORMAT_VERSION` 固定为 `0`**:预发布阶段不承诺广泛兼容性;`Session` 只接受当前 seed 形状,后端拒绝任何其他版本,不认识的事件类型也会拒绝重建,除非信封带 `ignorable` 标记([机制](../../../.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.zh.md))。
183
+ - **`fork()` 仅在实时会话的稳定边界处切分**:所选前缀结束时不得有开放轮次,且源会话必须位于存储中;fork API 不支持对已持久化但未加载的会话进行 fork。
184
+ - **`SESSION_FORMAT_VERSION` 命名当前 V3 逻辑表示**——V3 读取器拒绝已退役的 `header.system`,并校验 `system/message` 载荷与受保护头节点的重写。历史 header 与事件归相邻格式包所有;V2→V3 迁移边在构造 `Session` 前转换受支持的历史,写打开只发布 V3 后继代际。同版本未知事件要求信封显式带有 `ignorable` 标记,但这不保证结构迁移的安全性([机制](../../../.agents/notes/implemented/architecture/2026-08-31-released-session-format-migrations.zh.md))。
182
185
  - **`TurnEndReasonMap` 不含 ACP(Agent Client Protocol)命名的 `refusal`/`max_turn_requests` 变体**:受生产方约束;只有当适配器或循环首次产生这些变体时才加入。
183
186
  - **fork 之外没有会话树**:基于分支会话的 pi 风格条目树被推迟,除非消费方需要超越基于边界的 forking 的能力。
184
187