dsh-plugin-dev-kb 1.0.9 → 1.1.0
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/CHANGELOG.md +10 -0
- package/README.en.md +6 -6
- package/README.md +6 -6
- package/kb/INDEX.md +4 -2
- package/kb/README.md +4 -4
- package/kb/extra/AGENTS.md +1 -1
- package/kb/extra/cookbook/adding-a-remote-api.md +197 -0
- package/kb/extra/cookbook/adding-a-remote-api.zh.md +197 -0
- package/kb/extra/deepseek-llm-api-wire-extensions.md +18 -14
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +18 -14
- package/kb/extra/event-producer-consumer.md +44 -43
- package/kb/extra/event-producer-consumer.zh.md +47 -46
- package/kb/extra/i18n/style-samples.md +2 -2
- package/kb/extra/module-graph.md +444 -991
- package/kb/extra/module-graph.zh.md +446 -993
- package/kb/extra/subsystems/agent-team.md +4 -3
- package/kb/extra/subsystems/agent-team.zh.md +4 -3
- package/kb/extra/subsystems/attachment.md +157 -4
- package/kb/extra/subsystems/attachment.zh.md +157 -4
- package/kb/extra/subsystems/feedback.md +2 -2
- package/kb/extra/subsystems/feedback.zh.md +2 -2
- package/kb/extra/testing.md +6 -2
- package/kb/extra/testing.zh.md +6 -2
- package/kb/extra/web-styling.md +4 -0
- package/kb/extra/web-styling.zh.md +4 -0
- package/kb/meta/search-index.json +135 -111
- package/kb/meta/site-pages.txt +184 -182
- package/kb/meta/source.json +5 -5
- package/kb/meta/topics.md +4 -4
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/en/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/guide/network-proxy.md +87 -0
- package/kb/site/en/guide/providers.md +70 -17
- package/kb/site/en/guide/schedule.md +2 -0
- package/kb/site/en/reference/agent-lifecycle.md +5 -3
- package/kb/site/en/reference/api-gateway.md +2 -2
- package/kb/site/en/reference/capability-seams.md +14 -7
- package/kb/site/en/reference/config-catalog.md +157 -230
- package/kb/site/en/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/en/reference/cookbook/extension-cookbook.md +15 -12
- package/kb/site/en/reference/index.md +11 -4
- package/kb/site/en/reference/persistence-catalog.md +91 -70
- package/kb/site/en/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/en/reference/subsystems/commands.md +25 -16
- package/kb/site/en/reference/subsystems/compaction.md +9 -9
- package/kb/site/en/reference/subsystems/conversation.md +11 -4
- package/kb/site/en/reference/subsystems/core.md +96 -15
- package/kb/site/en/reference/subsystems/credentials.md +5 -4
- package/kb/site/en/reference/subsystems/goal.md +1 -1
- package/kb/site/en/reference/subsystems/index.md +1 -1
- package/kb/site/en/reference/subsystems/llm-streaming.md +24 -3
- package/kb/site/en/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/en/reference/subsystems/persistence.md +185 -194
- package/kb/site/en/reference/subsystems/plan.md +3 -3
- package/kb/site/en/reference/subsystems/sandbox.md +2 -0
- package/kb/site/en/reference/subsystems/schedule.md +9 -3
- package/kb/site/en/reference/subsystems/session-projection.md +50 -24
- package/kb/site/en/reference/subsystems/session-query.md +19 -13
- package/kb/site/en/reference/subsystems/session-reference.md +25 -1
- package/kb/site/en/reference/subsystems/session-telemetry.md +6 -5
- package/kb/site/en/reference/subsystems/session-title.md +6 -6
- package/kb/site/en/reference/subsystems/session.md +156 -73
- package/kb/site/en/reference/subsystems/settings.md +30 -12
- package/kb/site/en/reference/subsystems/skills.md +1 -1
- package/kb/site/en/reference/subsystems/slots.md +1 -0
- package/kb/site/en/reference/subsystems/storage.md +28 -5
- package/kb/site/en/reference/subsystems/subagent.md +43 -97
- package/kb/site/en/reference/subsystems/system-prompt.md +16 -3
- package/kb/site/en/reference/subsystems/token-meter.md +2 -2
- package/kb/site/en/reference/subsystems/typert.md +18 -18
- package/kb/site/en/reference/subsystems/web-client.md +1 -1
- package/kb/site/en/reference/subsystems/workspace.md +8 -8
- package/kb/site/en/reference/tool-catalog.md +10 -64
- package/kb/site/guide/network-proxy.md +87 -0
- package/kb/site/guide/providers.md +70 -17
- package/kb/site/guide/schedule.md +2 -0
- package/kb/site/reference/agent-lifecycle.md +5 -3
- package/kb/site/reference/api-gateway.md +2 -2
- package/kb/site/reference/capability-seams.md +14 -7
- package/kb/site/reference/config-catalog.md +156 -229
- package/kb/site/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/reference/cookbook/extension-cookbook.md +15 -12
- package/kb/site/reference/index.md +11 -4
- package/kb/site/reference/persistence-catalog.md +91 -70
- package/kb/site/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/reference/subsystems/commands.md +25 -16
- package/kb/site/reference/subsystems/compaction.md +9 -9
- package/kb/site/reference/subsystems/conversation.md +11 -4
- package/kb/site/reference/subsystems/core.md +96 -15
- package/kb/site/reference/subsystems/credentials.md +5 -4
- package/kb/site/reference/subsystems/goal.md +1 -1
- package/kb/site/reference/subsystems/index.md +1 -1
- package/kb/site/reference/subsystems/llm-streaming.md +24 -3
- package/kb/site/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/reference/subsystems/persistence.md +184 -193
- package/kb/site/reference/subsystems/plan.md +3 -3
- package/kb/site/reference/subsystems/schedule.md +9 -3
- package/kb/site/reference/subsystems/session-projection.md +50 -24
- package/kb/site/reference/subsystems/session-query.md +19 -13
- package/kb/site/reference/subsystems/session-reference.md +25 -1
- package/kb/site/reference/subsystems/session-telemetry.md +6 -5
- package/kb/site/reference/subsystems/session-title.md +6 -6
- package/kb/site/reference/subsystems/session.md +156 -73
- package/kb/site/reference/subsystems/settings.md +30 -12
- package/kb/site/reference/subsystems/skills.md +1 -1
- package/kb/site/reference/subsystems/slots.md +1 -0
- package/kb/site/reference/subsystems/storage.md +28 -5
- package/kb/site/reference/subsystems/subagent.md +43 -97
- package/kb/site/reference/subsystems/system-prompt.md +16 -3
- package/kb/site/reference/subsystems/token-meter.md +2 -2
- package/kb/site/reference/subsystems/typert.md +18 -18
- package/kb/site/reference/subsystems/web-client.md +1 -1
- package/kb/site/reference/subsystems/workspace.md +8 -8
- package/kb/site/reference/tool-catalog.md +9 -63
- package/package.json +2 -2
- package/skills/dsh-plugin-dev-kb.md +4 -4
|
@@ -37,11 +37,11 @@ interface CompactionResult {
|
|
|
37
37
|
/** Human command that initiated this compaction, when it was manual. */
|
|
38
38
|
sourceCommandId?: CommandId
|
|
39
39
|
/** The seq of the appended `compaction/start` event. */
|
|
40
|
-
startSeq:
|
|
40
|
+
startSeq: SessionSeq
|
|
41
41
|
/** The seq of the appended `compaction/summary` event. */
|
|
42
|
-
summarySeq:
|
|
42
|
+
summarySeq: SessionSeq
|
|
43
43
|
/** The seq of the appended `compaction/end` event. */
|
|
44
|
-
endSeq:
|
|
44
|
+
endSeq: SessionSeq
|
|
45
45
|
/** The summary content blocks produced by the backend. */
|
|
46
46
|
summary: ContentBlock[]
|
|
47
47
|
/**
|
|
@@ -52,9 +52,9 @@ interface CompactionResult {
|
|
|
52
52
|
* can be GREATER than `end`. {@link CompactionResult.shadowedSeqs} is the
|
|
53
53
|
* authoritative set of shadowed nodes, in surface order.
|
|
54
54
|
*/
|
|
55
|
-
shadowedRange: { start:
|
|
55
|
+
shadowedRange: { start: SessionSeq; end: SessionSeq }
|
|
56
56
|
/** The seqs of all shadowed surface nodes, in surface order. */
|
|
57
|
-
shadowedSeqs:
|
|
57
|
+
shadowedSeqs: SessionSeq[]
|
|
58
58
|
/** Estimated token count of the shadowed content. */
|
|
59
59
|
shadowedTokenCount: number
|
|
60
60
|
}
|
|
@@ -98,9 +98,9 @@ type ManualCompactionErrorCode =
|
|
|
98
98
|
/** Cited source event and size accounting for one landed surface replacement. */
|
|
99
99
|
interface PrunedEntry {
|
|
100
100
|
/** Full-fidelity tool-result event shadowed by the replacement. */
|
|
101
|
-
readonly originalSeq:
|
|
101
|
+
readonly originalSeq: SessionSeq
|
|
102
102
|
/** Newly appended pruned tool-result event. */
|
|
103
|
-
readonly replacementSeq:
|
|
103
|
+
readonly replacementSeq: SessionSeq
|
|
104
104
|
/** Tool call shared by the original and replacement. */
|
|
105
105
|
readonly callId: ToolCallId
|
|
106
106
|
/** Original text size in Unicode code points. */
|
|
@@ -190,10 +190,10 @@ abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, sour
|
|
|
190
190
|
* @throws when compaction is active or the range is missing, reversed, or unbalanced.
|
|
191
191
|
* @returns the appended event seqs, summary, replaced range, and token accounting.
|
|
192
192
|
*/
|
|
193
|
-
abstract compactRegion( start:
|
|
193
|
+
abstract compactRegion( start: SessionSeq, end: SessionSeq, agent: CompactionAgentContext, signal?: AbortSignal, ): Promise<CompactionResult>
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
-
Types: [CommandId](./commands.md)
|
|
196
|
+
Types: [CommandId](./commands.md) · [SessionSeq](./session.md)
|
|
197
197
|
|
|
198
198
|
Source: [`packages/compaction/compaction/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/compaction/compaction/src/index.ts)
|
|
199
199
|
|
|
@@ -11,18 +11,24 @@ Conversation 是 Client `SessionEventLikeEntry` window 与浏览器 view 之间
|
|
|
11
11
|
|
|
12
12
|
## 数据模型与所有权
|
|
13
13
|
|
|
14
|
-
Session Controller 拥有连续的已加载逻辑 event window。每个 `SessionEventLikeEntry`
|
|
14
|
+
Session Controller 拥有连续的已加载逻辑 event window。每个 `SessionEventLikeEntry` 要么是表示一个持久事件的 `{ type: 'event', event: SessionEvent }`,要么是表示一个 Client-only `assistant/live-chunk` 呈现的 `{ type: 'transient', event: AssistantLiveChunkEvent }`;两种内部 event 都公开 `type`、`seq`、`time` 与 `data`。`ui-conversation` 把这些 entry 直接交给 assembler,不另开 history stream。每个 Session 对应一个 `ConversationNodeAssembler`,它应用所有已注册 Definition,并为每个已注册 view target 发布独立 source。
|
|
15
15
|
|
|
16
16
|
| 概念 | Owner 与用途 |
|
|
17
17
|
|---|---|
|
|
18
|
-
| Event Definition |
|
|
19
|
-
| Context | Engine 为一个 `(kind, id)` 拥有的有序 Match 与当前 State
|
|
18
|
+
| Event Definition | 业务包一次匹配一个持久 event 或 Client-only 瞬态 event,以稳定 `(kind, id)` 关联输入、折叠确定性 State,并可选择 materialize 一个 target node。 |
|
|
19
|
+
| Context | Engine 为一个 `(kind, id)` 拥有的有序 Match 与当前 State。一个瞬态 event 只占一个 update Match;只有 update 的证据可以保持 pending,直到分页补齐其唯一持久 start。 |
|
|
20
20
|
| Location | Engine 根据持久 boundary event 推导的 Session、Turn 或 Step 坐标。Definition 可以向一个 Turn 或 Step 发布类型化数据。 |
|
|
21
21
|
| View Definition | Target 包为每个 Session 创建一个增量 builder,并拥有该 target 的最终 snapshot 类型。 |
|
|
22
22
|
| View | Chat 或 Trajectory 等 Slot entry 只读取自身 target snapshot,并渲染 target 自有 node。 |
|
|
23
23
|
|
|
24
24
|
Chat 与 Trajectory 可以识别同一个持久 event family,但各自保留自己的 Definition State 与最终 node payload。共享的 target-neutral 机制只包括 identity routing、有序 replay、Location data、predecessor dependency 与 publication cadence。
|
|
25
25
|
|
|
26
|
+
## Target 激活
|
|
27
|
+
|
|
28
|
+
每个 Session 都保留单调增长的 active target 集合。创建或读取 target source 不会激活它。shell 会显式激活持久化选择或新选择的 View,其他消费者则通过 target source 的首个订阅激活 target。首次激活会创建该 target 的 builder,并从当前按 target 索引的 Context 调用一次 `replace()`。后续 flush 对每个 active target 调用 `apply()`,取消订阅不会移除 target。
|
|
29
|
+
|
|
30
|
+
shell 拥有 View 选择,并在 binding 创建、被选为 current 或 View roster 变化时,于渲染前解析已注册的偏好 View 或 Chat fallback。assembler 只接收解析后的 target id,不自行选择 Chat 或其他默认 target。第三方 View 使用相同的选择与激活操作。
|
|
31
|
+
|
|
26
32
|
## 可回放 event family
|
|
27
33
|
|
|
28
34
|
编写 Definition 前先选定稳定的业务 id。构成同一个 Node 的每条事件都必须携带该 id,或只凭自身 payload 独立推导出该 id;Client 绝不能把 update 猜测为属于“最近一个未完成”的 Context。
|
|
@@ -39,7 +45,7 @@ Chat 与 Trajectory 可以识别同一个持久 event family,但各自保留
|
|
|
39
45
|
|
|
40
46
|
系统支持增量事件。如果生产方能以较低成本发出 whole-value checkpoint,应优先采用,因为 start 位于已加载窗口之外时它仍可直接使用。每条 delta 都必须携带稳定 id,并且按照日志 `seq` 升序回放时能够确定性地产生 State;它不能依赖只存在于实时内存中的状态。如果当前历史窗口只有 update,Assembler 会保留一个 pending Context,并在更早分页补齐 start 前不构造 State。如果产品必须在 start 尚未加载时渲染,terminal 或 checkpoint 事件就必须携带足够的完整 fallback 状态,让 Definition 能直接构造结果;不要通过扫描无关事件恢复它。
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
实时 Assistant delta 作为 Client-only `assistant/live-chunk` update 到达。重连 baseline 会把活跃的进程内紧凑 stream 展开为相同的瞬态 event,持久 `assistant/message` 与 `assistant/attempt` event 则嵌入完整紧凑 stream 供历史回放。瞬态 event 只能充当 update;`start()` 只接收标准 `SessionEvent`。消费 Assistant 输出的 Definition 在同一组 `match()` 与 `update()` 方法里处理 live chunk 与持久 settlement,其他 Definition 直接返回 `null`,无需展开 stream。
|
|
43
49
|
|
|
44
50
|
## Definition 与类型化 Chat payload
|
|
45
51
|
|
|
@@ -250,5 +256,6 @@ Assembler 会记录这项依赖。如果后续 older prepend 带来了更近的
|
|
|
250
256
|
5. 重复的可见 delta 保持 `context.key`,并在请求 `animation-frame` 时每帧最多发布一次。
|
|
251
257
|
6. keyed renderer 只消费 `node.data` 与受限 Location hook,不扫描 Session 事件窗口、Context 或 Chat Node。
|
|
252
258
|
7. scalar 与 packed Assistant 历史产生相同的最终 State、timing boundary 和 target snapshot;一个 packed run 在 replace、prepend、Location replay 与 registry rebuild 中始终只保留一个 Match。
|
|
259
|
+
8. 创建 target source 不执行 builder 工作;显式选择或首次订阅执行一次完整 replace,后续更新送达所有 active target,重复激活不会再次 replace。
|
|
253
260
|
|
|
254
261
|
流式与中断处理可参考 [`packages/client/ui-chat/src/client/conversation-nodes/assistant.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/assistant.ts),前序查询可参考 [`inbox.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/inbox.ts) 与 [`message.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/message.ts),只发布 Turn data 而不创建自有 Node 的例子见 [`packages/client/ui-deliverables`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/client/ui-deliverables)。
|
|
@@ -20,7 +20,7 @@ outline: [2,3]
|
|
|
20
20
|
| `agent-loop/` | 实现公开 `Agent` 约定的具体 driver(`ctx.agentLoop`) | 本页 |
|
|
21
21
|
| `scope/` | 注册表与循环用于构建按 agent 作用域的注册原语 | [scope.md](./scope.md) |
|
|
22
22
|
|
|
23
|
-
`scope/` 是这里唯一的非服务包:一个零依赖库(`createScope`/`scopeOf`/`scopeTarget`),在模块图中位于 `session/` 与 `system-prompt/` 之下,正是为了让它们消费它而不形成环。`agent-loop` 是公开 `Agent` 约定的唯一具体实现,放在这里因为它是 harness 的默认产品循环;它在 `ctx.agents.withInitiator()` 内运行每个 driver。扩展插件依赖 `agent`——包括需要发起 Agent 时——而绝不直接依赖 `agent-loop
|
|
23
|
+
`scope/` 是这里唯一的非服务包:一个零依赖库(`createScope`/`scopeOf`/`scopeTarget`),在模块图中位于 `session/` 与 `system-prompt/` 之下,正是为了让它们消费它而不形成环。`agent-loop` 是公开 `Agent` 约定的唯一具体实现,放在这里因为它是 harness 的默认产品循环;它在 `ctx.agents.withInitiator()` 内运行每个 driver。扩展插件依赖 `agent`——包括需要发起 Agent 时——而绝不直接依赖 `agent-loop`,因此循环保持可替换。[`dsh-base`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/base/README.zh.md) 是默认产品组合,[`dsh-sdk-minimal`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/sdk-minimal/README.zh.md) 则声明一棵更小的独立配置树。
|
|
24
24
|
|
|
25
25
|
<a id="creation-and-ownership"></a>
|
|
26
26
|
|
|
@@ -51,7 +51,7 @@ interface AgentHandle {
|
|
|
51
51
|
}
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
`CreateAgentOptions` 携带共享标识以及新 agent 发布前所需的一切:会话元数据(`meta`——已校验的 `cwd`、fork
|
|
54
|
+
`CreateAgentOptions` 携带共享标识以及新 agent 发布前所需的一切:会话元数据(`meta`——已校验的 `cwd`、fork 谱系、`isSeeded` 标记、来源分类、委派深度与 `agentPreset`)、同级字段 `inheritedEventCount` 所表示的精确 fork cut、可选的 `seed` 回放前缀、按 agent 的 `AgentOptions`、仅创建期有效的取消 `signal`,以及 `setup`。`ResumeAgentOptions` 是持久标识的对应项:`resumeSessionId`、`agentOptions`、`signal` 与 `setup`。`setup` 回调(`AgentSetup`)在两个 id 都尚未发布时组装 agent 的作用域世界——凡经 `agentCtx` 注册的内容都先于 `agent/created` 与第一次提示词组装存在——并可返回一个在发布前一刻调用的同步 commit;setup 拒绝、commit 抛出或所有者 dispose(资源释放)都会回滚事务,两个 id 均不发布。
|
|
55
55
|
|
|
56
56
|
`AgentFactory` 是注册表背后的创建接口:循环经 `ctx.agents.setFactory()` 注册其工厂,因此消费方使用 `ctx.agents` 时无需依赖具体循环包。确切的 `create`/`resume` 签名及回滚约定见下方[生成区块](#ctxagents--agentregistry)。
|
|
57
57
|
|
|
@@ -159,6 +159,44 @@ interface Agent {
|
|
|
159
159
|
type AgentStatus = 'idle' | 'running'
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
+
```ts type-equiv
|
|
163
|
+
/** One process-local live assistant streaming publication. */
|
|
164
|
+
type AssistantStreamFrame =
|
|
165
|
+
| {
|
|
166
|
+
readonly type: 'start'
|
|
167
|
+
readonly attemptId: LlmAttemptId
|
|
168
|
+
/** Monotone within one attached Agent lifecycle; replacement restarts at 1. */
|
|
169
|
+
readonly revision: number
|
|
170
|
+
readonly turn: number
|
|
171
|
+
readonly step: number
|
|
172
|
+
}
|
|
173
|
+
| {
|
|
174
|
+
readonly type: 'chunk'
|
|
175
|
+
readonly attemptId: LlmAttemptId
|
|
176
|
+
readonly revision: number
|
|
177
|
+
/** Dense zero-based position within the attempt. */
|
|
178
|
+
readonly index: number
|
|
179
|
+
/** Safe-integer timestamp reused by the durable embedded stream. */
|
|
180
|
+
readonly time: number
|
|
181
|
+
readonly chunk: StreamChunk
|
|
182
|
+
}
|
|
183
|
+
| {
|
|
184
|
+
readonly type: 'end'
|
|
185
|
+
readonly attemptId: LlmAttemptId
|
|
186
|
+
readonly revision: number
|
|
187
|
+
/** Number of chunk frames emitted by this attempt. */
|
|
188
|
+
readonly index: number
|
|
189
|
+
/** Durable settlement committed before this notification, or live abandonment without one. */
|
|
190
|
+
readonly outcome:
|
|
191
|
+
| {
|
|
192
|
+
readonly kind: 'committed'
|
|
193
|
+
readonly eventType: 'assistant/message' | 'assistant/attempt'
|
|
194
|
+
readonly seq: SessionSeq
|
|
195
|
+
}
|
|
196
|
+
| { readonly kind: 'abandoned' }
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
162
200
|
`running` 描述整个驱动器的排空区间,可能跨越连续的排队轮次;它不能证明某个轮次仍然打开。dispose 会把 agent 从注册表移除并发出 `agent/disposed`;它不是一个终态 status 值。`followup()` 不返回句柄:其 `MessageId` 标识的是持久的 inbox 插入、认领与丢弃事实,而非之后的助手输出或轮次结束。`whenIdle()` 观察的是整个 agent,因此只有当调用方明确拥有从回执到空闲的这段区间时,才能把它称为一次 run([决策](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.zh.md))。
|
|
163
201
|
|
|
164
202
|
```ts type-equiv
|
|
@@ -263,7 +301,7 @@ type SessionStartSource = 'startup' | 'resume' | 'clear' | 'compact'
|
|
|
263
301
|
|
|
264
302
|
`Session` 是一份类型化 `SessionEvent` 的**仅追加日志**——唯一的真源。LLM 消息历史从日志*派生*(`deriveMessages()`),而非单独存储。每个条目携带单调的 `seq`、`time` 与按 `type` 判别的 `data` payload;surface 变体还可以在 `sourceEventSeqs` 中列出被引用的较早事件,并携带 `surfaceOp`。
|
|
265
303
|
|
|
266
|
-
`SessionEvent` 信封的确切条件字段、十二种核心事件变体(`turn/start`、`turn/end`、`step/start`、`step/end`、`user/message`、`assistant/
|
|
304
|
+
`SessionEvent` 信封的确切条件字段、十二种核心事件变体(`turn/start`、`turn/end`、`step/start`、`step/end`、`user/message`、`assistant/message`、`assistant/attempt`、`tool/call`、`tool/result`、`request/header`、`request/context`、`session/end-seed`)、`deriveMessages()` 投影规则、`TurnEndReason` 原因以及执行封闭和独立事件规则都在 **[session.md](./session.md)** 中。日志如何持久化——`SessionPersistence` 接口、JSONL provider、`session/flush` 检查点、崩溃恢复与 `SessionHeader`——则在 **[persistence.md](./persistence.md)** 中。
|
|
267
305
|
|
|
268
306
|
## `ToolDefinition`
|
|
269
307
|
|
|
@@ -314,9 +352,9 @@ declare module '@deepseek-ai/dsh-llm' {
|
|
|
314
352
|
|
|
315
353
|
### 品牌化 ID
|
|
316
354
|
|
|
317
|
-
在包之间传递的 ID 都经过**品牌化**——结构上是字符串,但在类型层面不可互换(不能把 `SessionId` 传给需要 `ToolCallId`
|
|
355
|
+
在包之间传递的 ID 都经过**品牌化**——结构上是字符串,但在类型层面不可互换(不能把 `SessionId` 传给需要 `ToolCallId` 的位置)。构造使用共享 `brandString<T>()` helper 或所属方自定义的校验工厂;比较、日志记录和 JSON 行为与普通字符串相同。
|
|
318
356
|
|
|
319
|
-
`Branded<B>`
|
|
357
|
+
`Branded<B>` 原语与无状态构造函数位于 [dsh-brand](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/util/brand),该包不依赖 harness 能力。`brandString<T>()` 应用仅编译期存在的字符串品牌。
|
|
320
358
|
|
|
321
359
|
源码:[`packages/util/brand/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/util/brand/src/index.ts)
|
|
322
360
|
|
|
@@ -369,13 +407,14 @@ Concrete agent factory and driver service.
|
|
|
369
407
|
/**
|
|
370
408
|
* Create an agent and session under one caller-supplied identity, owned by
|
|
371
409
|
* the accessing fiber. Constructor-driven config calls mint a fresh combined
|
|
372
|
-
* id before entering this boundary.
|
|
410
|
+
* id before entering this boundary. When a persistence backend is mounted,
|
|
411
|
+
* the session's durable identity and any seed are stored before publication.
|
|
373
412
|
* @param id - shared agent/session identity.
|
|
374
413
|
* @param options - concrete loop options.
|
|
375
414
|
* @param meta - optional fresh-session workspace metadata.
|
|
376
415
|
* @returns the published running agent.
|
|
377
416
|
*/
|
|
378
|
-
create(id: SessionId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): Agent
|
|
417
|
+
async create(id: SessionId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): Promise<Agent>
|
|
379
418
|
|
|
380
419
|
/**
|
|
381
420
|
* Create an owned agent on a caller-supplied session id.
|
|
@@ -423,6 +462,25 @@ async list(): Promise<AgentPreset[]>
|
|
|
423
462
|
*/
|
|
424
463
|
@Remote('list') async remoteExportList(): Promise<AgentPresetRoster>
|
|
425
464
|
|
|
465
|
+
/**
|
|
466
|
+
* Every preset's composition as flattened plugin rows, for plugin-listing
|
|
467
|
+
* surfaces beside the roster's own picker.
|
|
468
|
+
*
|
|
469
|
+
* A preset with a live standing mount answers from its newest generation's
|
|
470
|
+
* Loader entries — the composition new sessions join — even when the file
|
|
471
|
+
* behind it has since been edited into an unreadable state: the mount is
|
|
472
|
+
* what sessions actually run, so the broken verdict only applies to a
|
|
473
|
+
* preset nothing composed. One never composed since boot answers from its
|
|
474
|
+
* file, with `!!js` disabled gates evaluated against the Loader context so
|
|
475
|
+
* both answers reflect the same host. Reading never mounts: an unmounted
|
|
476
|
+
* preset is parsed, not composed, so listing a preset's plugins cannot
|
|
477
|
+
* activate them early. A composition that stopped reading between
|
|
478
|
+
* discovery's health verdict and this read is reported broken with the
|
|
479
|
+
* raced reason rather than dropped.
|
|
480
|
+
* @returns one composition per roster preset, in roster order.
|
|
481
|
+
*/
|
|
482
|
+
async compositionInventory(): Promise<AgentPresetComposition[]>
|
|
483
|
+
|
|
426
484
|
/**
|
|
427
485
|
* Resolve one preset by id.
|
|
428
486
|
*
|
|
@@ -501,8 +559,8 @@ async read(id: string): Promise<string>
|
|
|
501
559
|
* One preset's composition text with the roster row it belongs to.
|
|
502
560
|
* @param agentPreset - the preset id.
|
|
503
561
|
* @returns the composition beside its trust and published metadata.
|
|
504
|
-
* @throws {
|
|
505
|
-
* `agent-preset
|
|
562
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty id, or
|
|
563
|
+
* `agent-preset/not-found` when no configured root supplies it.
|
|
506
564
|
*/
|
|
507
565
|
@Remote('read') async readDocument(agentPreset: string): Promise<AgentPresetDocument>
|
|
508
566
|
|
|
@@ -529,8 +587,8 @@ async copy(from: string, id: string, name?: string): Promise<void>
|
|
|
529
587
|
* @param id - the new preset id.
|
|
530
588
|
* @param name - the copy's optional display name.
|
|
531
589
|
* @returns once the copy is stored.
|
|
532
|
-
* @throws {
|
|
533
|
-
*
|
|
590
|
+
* @throws {RemoteError} with the corresponding stable preset code and
|
|
591
|
+
* details when the copy is refused.
|
|
534
592
|
*/
|
|
535
593
|
@Remote('copy') async remoteExportCopy(from: string, id: string, name?: string): Promise<void>
|
|
536
594
|
|
|
@@ -546,8 +604,8 @@ async remove(id: string): Promise<void>
|
|
|
546
604
|
* Delete one preset through the Remote API.
|
|
547
605
|
* @param id - the preset id.
|
|
548
606
|
* @returns once the preset is deleted.
|
|
549
|
-
* @throws {
|
|
550
|
-
*
|
|
607
|
+
* @throws {RemoteError} with the corresponding stable preset code and
|
|
608
|
+
* details when deletion is refused.
|
|
551
609
|
*/
|
|
552
610
|
@Remote('deletePreset') async remoteExportDelete(id: string): Promise<void>
|
|
553
611
|
|
|
@@ -598,8 +656,8 @@ async recompose(agentCtx: Context, id: string): Promise<AgentPreset>
|
|
|
598
656
|
* @param agent - the session's live agent, resolved from the wire identity.
|
|
599
657
|
* @param agentPreset - the preset to compose the agent from instead.
|
|
600
658
|
* @returns the preset id that was recorded.
|
|
601
|
-
* @throws {
|
|
602
|
-
* `agent-preset
|
|
659
|
+
* @throws {RemoteError} with `gateway/bad-request`, `agent-preset/locked`,
|
|
660
|
+
* `agent-preset/not-found`, or `agent-preset/invalid` when refused.
|
|
603
661
|
*/
|
|
604
662
|
@Remote('select') async select(agent: Agent, agentPreset: string): Promise<string>
|
|
605
663
|
|
|
@@ -797,6 +855,29 @@ Source: [`packages/core/agent/src/index.ts`](https://github.com/deepseek-ai/deep
|
|
|
797
855
|
|
|
798
856
|
### `agent/*` events
|
|
799
857
|
|
|
858
|
+
<a id="agentassistant-stream--emit"></a>
|
|
859
|
+
|
|
860
|
+
#### `agent/assistant-stream` — emit
|
|
861
|
+
|
|
862
|
+
Process-local assistant-stream publication. Chunk frames are transient; the loop appends one final v2 `assistant/message` or `assistant/attempt` with the same stream before a committed end frame.
|
|
863
|
+
|
|
864
|
+
```ts cordis-catalog
|
|
865
|
+
/**
|
|
866
|
+
* Process-local assistant-stream publication. Chunk frames are transient;
|
|
867
|
+
* the loop appends one final v2 `assistant/message` or `assistant/attempt`
|
|
868
|
+
* with the same stream before a committed end frame.
|
|
869
|
+
* @param payload.agent - the agent whose attempt produced the frame.
|
|
870
|
+
* @param payload.frame - one ordered start, chunk, or end publication.
|
|
871
|
+
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
|
872
|
+
* @mode emit
|
|
873
|
+
*/
|
|
874
|
+
'agent/assistant-stream'(this: Scoped<Agent>, payload: { agent: Agent; frame: AssistantStreamFrame }): void
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
Types: [Scoped](./scope.md)
|
|
878
|
+
|
|
879
|
+
Source: [`packages/core/agent/src/runtime-types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent/src/runtime-types.ts)
|
|
880
|
+
|
|
800
881
|
<a id="agentcreated--emit"></a>
|
|
801
882
|
|
|
802
883
|
#### `agent/created` — emit
|
|
@@ -230,9 +230,10 @@ Host service backing the generated `ctx.remote.credentials` namespace. It carrie
|
|
|
230
230
|
* Describe several references for one configuration surface. Batched because
|
|
231
231
|
* a settings page describes every reference its rows name at once, and one
|
|
232
232
|
* round trip keeps those rows from settling separately.
|
|
233
|
-
* @param refs - reference names, at most {@link MAX_DESCRIBE_REFS}; a name outside the grammar
|
|
233
|
+
* @param refs - reference names, at most {@link MAX_DESCRIBE_REFS}; a name outside the grammar
|
|
234
|
+
* rejects the whole call as `gateway/bad-request`.
|
|
234
235
|
* @returns one view per requested name, keyed by that name.
|
|
235
|
-
* @throws
|
|
236
|
+
* @throws RemoteError when the request is invalid or no credential provider is mounted.
|
|
236
237
|
*/
|
|
237
238
|
@Remote async describe(refs: string[]): Promise<Record<string, CredentialInfo>>
|
|
238
239
|
|
|
@@ -241,14 +242,14 @@ Host service backing the generated `ctx.remote.credentials` namespace. It carrie
|
|
|
241
242
|
* this direction only: no read path returns it.
|
|
242
243
|
* @param ref - reference name to store under.
|
|
243
244
|
* @param value - the non-empty secret value.
|
|
244
|
-
* @throws
|
|
245
|
+
* @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
|
|
245
246
|
*/
|
|
246
247
|
@Remote async set(ref: string, value: string): Promise<void>
|
|
247
248
|
|
|
248
249
|
/**
|
|
249
250
|
* Remove one reference from a configuration surface.
|
|
250
251
|
* @param ref - reference name to remove.
|
|
251
|
-
* @throws
|
|
252
|
+
* @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
|
|
252
253
|
*/
|
|
253
254
|
@Remote async unset(ref: string): Promise<void>
|
|
254
255
|
```
|
|
@@ -145,7 +145,7 @@ interface GoalChanged {
|
|
|
145
145
|
|
|
146
146
|
## 服务行为
|
|
147
147
|
|
|
148
|
-
[`GoalService`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/src/index.ts)
|
|
148
|
+
[`GoalService`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/src/index.ts) 解析创建默认值、从可选注册的 `goal` 投影读取严格回放结果、校验传入的 agent(智能体)是注册表中的确切活跃实例、以比较并设置方式执行变更,并发出 `goal/changed` 通知;监听器故障会被隔离。注册表或 key 缺失时,第一次依赖它们的访问会失败。包 [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/README.zh.md) 定义可调用 API 和面向模型的约定。
|
|
149
149
|
|
|
150
150
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
151
151
|
|
|
@@ -19,7 +19,7 @@ outline: [2,3]
|
|
|
19
19
|
| [todo.md](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/todo.zh.md) | todo 包的整列表条目类型、持久事件所有权、投影和开放轮次不变量 |
|
|
20
20
|
| [commands.md](./commands.md) | 人类命令注册表服务:定义、适配器发现、直接调用、结果与解析视图 |
|
|
21
21
|
| [session.md](./session.md) | 完整的 `SessionEventMap` 变体目录、`TurnEndReason`、`deriveMessages()`、执行封闭与独立事件 |
|
|
22
|
-
| [persistence.md](./persistence.md) | 持久性 seam:`SessionPersistence`、JSONL
|
|
22
|
+
| [persistence.md](./persistence.md) | 持久性 seam:`SessionPersistence`、JSONL provider、`session/flush`、崩溃恢复、`SessionHeader` |
|
|
23
23
|
| [settings.md](./settings.md) | 用户设置 seam:`SettingsNamespace` 注册、分层解析(默认值 → 组合 `base` → 用户文档)、owner scope、热提交 |
|
|
24
24
|
| [credentials.md](./credentials.md) | 凭据 seam:配置中的 `CredentialRef` 引用(绝不含值)、按操作解析、对 UI 安全的 `CredentialInfo`、提供方来源层 |
|
|
25
25
|
| [session-query.md](./session-query.md) | 逻辑记录、有界精确事件读取、关系追踪、语义筛选器/文档与全文检索结果页 |
|
|
@@ -26,12 +26,13 @@ interface ContentBlockMap {
|
|
|
26
26
|
'text': TextBlock
|
|
27
27
|
'reasoning': ReasoningBlock
|
|
28
28
|
'image': ImageBlock
|
|
29
|
+
'file': FileBlock
|
|
29
30
|
'tool-call': ToolCallBlock
|
|
30
31
|
'tool-result': ToolResultBlock
|
|
31
32
|
}
|
|
32
33
|
```
|
|
33
34
|
|
|
34
|
-
各块接口(完整字段见源码):`TextBlock`(`text`)、`ReasoningBlock`(thinking,区别于可见文本)、`ImageBlock`(一个持久的[图片附件](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.zh.md))、`ToolCallBlock`(`id: ToolCallId`、`name`、原始 JSON `arguments`),以及 `ToolResultBlock`(`toolCallId`、嵌套 `content: ContentBlock[]`、`isError?`)。`ContentBlock = ContentBlockMap[ContentBlockType]`。仅当适配器、UI、压缩(compaction)和持久回放路径均支持某种新模态时,才将其纳入可合并扩展的 map。
|
|
35
|
+
各块接口(完整字段见源码):`TextBlock`(`text`)、`ReasoningBlock`(thinking,区别于可见文本)、`ImageBlock`(一个持久的[图片附件](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.zh.md))、`FileBlock`(一个持久的原样[文件附件](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.zh.md),请求组装对每条路由都把它投影为 handle 文本)、`ToolCallBlock`(`id: ToolCallId`、`name`、原始 JSON `arguments`),以及 `ToolResultBlock`(`toolCallId`、嵌套 `content: ContentBlock[]`、`isError?`)。`ContentBlock = ContentBlockMap[ContentBlockType]`。仅当适配器、UI、压缩(compaction)和持久回放路径均支持某种新模态时,才将其纳入可合并扩展的 map。
|
|
35
36
|
|
|
36
37
|
图片访问方式属于请求序列化,不属于持久附件或确定性请求图片版本。`resolveImageAttachmentAccess()` 把附件提供方可选的宿主对象路径,与消费方为当前工具执行文件系统提供的映射组合起来。结果只适用于本次请求,不参与 `variantId`。
|
|
37
38
|
|
|
@@ -219,6 +220,16 @@ type StreamChunk =
|
|
|
219
220
|
}
|
|
220
221
|
```
|
|
221
222
|
|
|
223
|
+
<a id="compact-assistant-streams"></a>
|
|
224
|
+
|
|
225
|
+
## 紧凑 Assistant stream
|
|
226
|
+
|
|
227
|
+
`AssistantStreamAccumulator` 把每个 `StreamChunk` 与其原始安全整数时间戳配对,并生成 `AssistantStreamRecord[]`。同一 block 的连续 text、reasoning 或 tool argument delta 会变成一个 record,使用 `time0`、精确时间戳间隔和每个原始 delta 对应的一个数组成员;其他 chunk 保留为带时间戳的 raw record。该表示会移除重复 event envelope,但不会合并 token 边界,也不会丢弃 terminal、usage、block、failure 或 replay 事实。
|
|
228
|
+
|
|
229
|
+
`snapshot()` 返回分离且不可变的 stream。`expandAssistantStream()` 会严格检查 record key、成员数、index、时间戳、tool-call identity 与无损 JSON,再重建精确的带时间 chunk 序列。Session 日志会把该 stream 嵌入作为 surface result 的 `assistant/message`,或嵌入没有 surface message 的 `assistant/attempt`。
|
|
230
|
+
|
|
231
|
+
进程本地 `agent/assistant-stream` frame 承载实时呈现。持久回放、遥测、token 记账与历史 UI 组装会展开嵌入式 settlement,而不会把 live frame 当作持久事实。
|
|
232
|
+
|
|
222
233
|
<a id="llmfailure"></a>
|
|
223
234
|
|
|
224
235
|
## `LlmFailure`
|
|
@@ -285,7 +296,7 @@ interface LlmImageRequestPricing {
|
|
|
285
296
|
|
|
286
297
|
- **`usage` 在 `finish` 之前,`finish` 之后不再有任何分片。** 将两者都推迟到提供方的流结束标记,这样尾部的 usage-only 分片就不会违反顺序。
|
|
287
298
|
- **工具调用的 `arguments` 全程保持原始 JSON 字符串。** 部分片段通过 `argumentsDelta` 流式传输;如果提供方返回的是已解析的对象,适配器在 `block-end` 时重新序列化为字符串。
|
|
288
|
-
- **两条受支持的错误路径,共用一个 `LlmFailure` 类型。** 失败可以从 `stream()` 抛出(传输/协议错误),**或者**以 `finish {kind:'error'|'aborted', failure}` 结束流(无法在流中途抛异常的适配器用它表示提供方带内错误)。`LlmError.failure` 携带同一个 `LlmFailure`。调用选定适配器后,流会保留被抛出的确切 `Error` 对象,并将不可变事实以及实际服务注册所对应的不可变重试策略关联到该调用;agent loop
|
|
299
|
+
- **两条受支持的错误路径,共用一个 `LlmFailure` 类型。** 失败可以从 `stream()` 抛出(传输/协议错误),**或者**以 `finish {kind:'error'|'aborted', failure}` 结束流(无法在流中途抛异常的适配器用它表示提供方带内错误)。`LlmError.failure` 携带同一个 `LlmFailure`。调用选定适配器后,流会保留被抛出的确切 `Error` 对象,并将不可变事实以及实际服务注册所对应的不可变重试策略关联到该调用;agent loop(智能体循环)先把 attempt stream 提交为 `assistant/attempt`,再关闭失败步骤,并把错误、事实、不可变的先前已重试失败事实、实际服务策略和轮次信号提供给 `agent/request-error`。处理该错误的 listener 在其 await 的修复完成后返回 `{ kind: 'retry' }`;若未恢复,结构化失败会成为轮次错误,并且该次 attempt 不会提交 surface Assistant message 或工具副作用。
|
|
289
300
|
- **一次适配器调用就是一次提供方尝试。** 适配器禁用库重试。agent 层恢复会打开另一个持久、带编号的轮次;直接调用 `ctx.llm.stream()` 的调用方仍然只尝试一次。
|
|
290
301
|
- **提供方停顿在传输层受到时限约束。** 两个已交付的远程适配器都暴露正数且有限的 `streamIdleTimeoutMs`,默认五分钟。watchdog 只在 iterator `next()` 尚未完成时启动,整个请求使用同一个稳定 signal,把自身到期映射为 `TIMEOUT`,并把更早发生的调用方中止保留为 `ABORTED`。
|
|
291
302
|
- **上下文溢出只有一个规范 code。** 两个 DeepSeek 适配器都通过 `isContextWindowExceededError()` 对提供方的显式细节分类并暴露 `CONTEXT_WINDOW_EXCEEDED`,无论失败以抛出的 HTTP `LlmError` 还是带内 finish error 到达。消费方按 code 路由,绝不依赖提供方文本。
|
|
@@ -938,7 +949,7 @@ async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, sig
|
|
|
938
949
|
* @param request - endpoint, protocol, and one-shot credential to use.
|
|
939
950
|
* @param signal - caller cancellation supplied by the Remote carrier.
|
|
940
951
|
* @returns advertised models in endpoint order.
|
|
941
|
-
* @throws
|
|
952
|
+
* @throws RemoteError with `llm/model-discovery-rejected` when discovery refuses or fails.
|
|
942
953
|
*/
|
|
943
954
|
@Remote('discoverModels') async remoteDiscoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, signal: AbortSignal, ): Promise<LlmDiscoveredModel[]>
|
|
944
955
|
|
|
@@ -960,6 +971,14 @@ providerRetryPolicy(provider: string): ResolvedRetryPolicy
|
|
|
960
971
|
*/
|
|
961
972
|
imageRequestPricing(provider: string, model: string): LlmImageRequestPricing | undefined
|
|
962
973
|
|
|
974
|
+
/**
|
|
975
|
+
* Resolve the exact text one durable file occurrence contributes to every
|
|
976
|
+
* provider request in the current execution environment.
|
|
977
|
+
* @param ref - durable verbatim file reference from model history.
|
|
978
|
+
* @returns the same deterministic handle text used at adapter dispatch.
|
|
979
|
+
*/
|
|
980
|
+
fileRequestText(ref: FileAttachmentRef): string
|
|
981
|
+
|
|
963
982
|
/**
|
|
964
983
|
* Discover models advertised by one registered provider. Catalog membership
|
|
965
984
|
* is advisory and never changes routing or request validation.
|
|
@@ -1015,6 +1034,8 @@ async prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise<Prepared
|
|
|
1015
1034
|
stream(options: GenerateOptions): AsyncIterable<StreamChunk>
|
|
1016
1035
|
```
|
|
1017
1036
|
|
|
1037
|
+
Types: [FileAttachmentRef](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.zh.md)
|
|
1038
|
+
|
|
1018
1039
|
Source: [`packages/llm/llm/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/index.ts)
|
|
1019
1040
|
|
|
1020
1041
|
<a id="llm-events"></a>
|
|
@@ -48,7 +48,7 @@ interface Config {
|
|
|
48
48
|
|
|
49
49
|
## 当前预设与派生的 `custom`
|
|
50
50
|
|
|
51
|
-
`current(
|
|
51
|
+
`current(session)` 从可选注册的 `permissions` 投影派生实际生效的预设。该单元折叠会话的沙箱模式、审批策略和已记录选择;状态内部的缺失值回退到执行器配置的模式与审批服务配置,最后回退到 `ask`。注册表或投影 key 缺失时会显式失败。服务优先取仍然匹配的选择,其次取声明顺序中第一个匹配的表项,否则返回 `CUSTOM_PRESET`(`'custom'`)。`custom` 只是派生值:客户端可以把它显示为当前值,但它绝不是切换目标,也绝不出现在事件 payload 中。
|
|
52
52
|
|
|
53
53
|
`names` 按预设表声明顺序列出可切换的预设;`optionOf(name)` 为某个表键(label 回退为该键)或 `custom` 构建客户端渲染的选项,传入其他任何名称都会抛出异常。
|
|
54
54
|
|
|
@@ -68,7 +68,7 @@ interface PresetOption {
|
|
|
68
68
|
|
|
69
69
|
`set(session, name)` 解析预设(未知名称抛出异常),在 `name` 尚不是生效预设时追加一条仅记日志的 `permission/preset` 事件,然后通过各旋钮自己的 setter([dsh-sandbox-policy](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/sandbox/sandbox-policy) 的 `setSandboxMode` 与 [dsh-user-approval](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/interaction/user-approval) 的 `setApprovalPolicy`)写入,且仅当该 knob的生效值发生变化时才写。同一轮次内,选择事件先于旋钮事件出现;重新选择当前生效的预设则什么都不追加。
|
|
70
70
|
|
|
71
|
-
`permission/preset` 是持久、仅记日志的用户意图:它不进入模型 transcript(文本记录),模型可见的后果由 knob 事件经各自消费方承担;它存在是为了在两个预设共享同一个旋钮组合时,让 `current()`
|
|
71
|
+
`permission/preset` 是持久、仅记日志的用户意图:它不进入模型 transcript(文本记录),模型可见的后果由 knob 事件经各自消费方承担;它存在是为了在两个预设共享同一个旋钮组合时,让 `current()` 仍能保住用户选择的究竟是哪一个预设。`permissions` 投影把该选择与两个 knob 事件一同折叠,并保留用于区分空恢复 seed 与新会话的 `session/end-seed` 边界;回放不需要任何追赶状态或原始日志重扫。完整事件声明见[持久化日志事件目录](../persistence-catalog.md);方法签名见生成的[服务目录](#ctxpermissionpresets--permissionpresetservice)。
|
|
72
72
|
|
|
73
73
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
74
74
|
|
|
@@ -89,10 +89,10 @@ Owns the deployment's permission presets and their write path. Requires a confin
|
|
|
89
89
|
* Resolve the preset matching the effective knob values. A still-matching
|
|
90
90
|
* last selection wins shared-bundle ties; otherwise the first table match
|
|
91
91
|
* wins, or {@link CUSTOM_PRESET} when no entry matches.
|
|
92
|
-
* @param
|
|
92
|
+
* @param session - the session whose knob state is read.
|
|
93
93
|
* @returns the effective preset name, or `custom` when nothing matches.
|
|
94
94
|
*/
|
|
95
|
-
current(
|
|
95
|
+
current(session: Session): string
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
98
|
* Build the whole select value for one folded knob state: every table
|
|
@@ -128,7 +128,7 @@ optionOf(name: string): PresetOption
|
|
|
128
128
|
set(session: Session, name: string): void
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
Types: [Session](./session.md)
|
|
131
|
+
Types: [Session](./session.md)
|
|
132
132
|
|
|
133
133
|
Source: [`packages/interaction/permission-presets/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/permission-presets/src/index.ts)
|
|
134
134
|
<!-- END GENERATED cordis-surface -->
|