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 @@ The optional tool-result pruning service reports each durable content replacemen
|
|
|
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 @@ This page defines the data model and the extension path for a business-owned Con
|
|
|
11
11
|
|
|
12
12
|
## Data model and ownership
|
|
13
13
|
|
|
14
|
-
The Session Controller owns the contiguous loaded logical-event window. Each `SessionEventLikeEntry` is either `{ type: 'event', event: SessionEvent }` or `{ type: '
|
|
14
|
+
The Session Controller owns the contiguous loaded logical-event window. Each `SessionEventLikeEntry` is either `{ type: 'event', event: SessionEvent }` for one durable event or `{ type: 'transient', event: AssistantLiveChunkEvent }` for one Client-only `assistant/live-chunk` presentation. Both inner events expose `type`, `seq`, `time`, and `data`. `ui-conversation` passes these entries to the assembler without opening a second history stream. One `ConversationNodeAssembler` per Session applies every registered Definition and publishes an independent source for each registered view target.
|
|
15
15
|
|
|
16
16
|
| Concept | Owner and purpose |
|
|
17
17
|
|---|---|
|
|
18
|
-
| Event Definition | A business package matches one
|
|
19
|
-
| Context | The engine-owned ordered Matches and current State for one `(kind, id)`. A
|
|
18
|
+
| Event Definition | A business package matches one durable or Client-only transient event at a time, correlates it by stable `(kind, id)`, folds deterministic State, and optionally materializes one target node. |
|
|
19
|
+
| Context | The engine-owned ordered Matches and current State for one `(kind, id)`. A transient event occupies one update Match; update-only evidence may remain pending until pagination supplies its unique durable start. |
|
|
20
20
|
| Location | The engine-owned Session, Turn, or Step coordinates derived from durable boundary events. Definitions may publish typed data onto one Turn or Step. |
|
|
21
21
|
| View Definition | A target package creates one incremental builder per Session and owns the final snapshot type for that target. |
|
|
22
22
|
| View | A Slot entry such as Chat or Trajectory reads only its target snapshot and renders target-owned nodes. |
|
|
23
23
|
|
|
24
24
|
Chat and Trajectory may recognize the same durable event family, but each keeps its own Definition State and final node payload. Shared target-neutral machinery is limited to identity routing, ordered replay, Location data, predecessor dependencies, and publication cadence.
|
|
25
25
|
|
|
26
|
+
## Target activation
|
|
27
|
+
|
|
28
|
+
Each Session keeps a monotonic set of active targets. Creating or reading a target source does not activate it. The shell explicitly activates its persisted or newly selected View, while another consumer activates a target through its first source subscription. First activation creates that target's builder and calls `replace()` once from the current target-indexed Contexts. Later flushes call `apply()` for every active target, and unsubscription does not remove one.
|
|
29
|
+
|
|
30
|
+
The shell owns View selection and resolves the registered preferred View or Chat fallback before rendering when a binding is created or selected as current, and after View-roster changes. The assembler receives only the resolved target id and does not select Chat or another default target. A third-party View participates through the same selection and activation operations.
|
|
31
|
+
|
|
26
32
|
## Replayable event families
|
|
27
33
|
|
|
28
34
|
Choose one stable business id before writing the Definition. Every event that contributes to the same Node must carry that id or derive it independently from its own payload; the client must never assign an update to “the latest unfinished” Context.
|
|
@@ -39,7 +45,7 @@ Use the producer-owned branded id type across the process boundary. Put the `Ses
|
|
|
39
45
|
|
|
40
46
|
Incremental events are supported. Prefer whole-value checkpoints when the producer can emit them cheaply, because they remain useful when the start is outside the loaded window. Each delta must carry the stable id and produce deterministic State when replayed in ascending log `seq`; it must not depend on live-only memory. If the current history window contains only updates, the assembler keeps a pending Context and builds no State until an older page supplies the start. If the product must render before the start is loaded, a terminal or checkpoint event must carry enough whole fallback state for the Definition to build that result directly; do not recover it by scanning unrelated events.
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
Live Assistant deltas arrive as Client-only `assistant/live-chunk` updates. Reconnect baselines expand the active process-local compact stream into the same transient events, while durable `assistant/message` and `assistant/attempt` events embed complete compact streams for history replay. Transient events can only be updates; `start()` receives a standard `SessionEvent`. A Definition that consumes Assistant output handles live chunks and durable settlements in the same `match()` and `update()` methods, while unrelated Definitions return `null` without expanding a stream.
|
|
43
49
|
|
|
44
50
|
## Definition and typed Chat payload
|
|
45
51
|
|
|
@@ -250,5 +256,6 @@ Add focused tests that establish these outcomes:
|
|
|
250
256
|
5. Repeated visible deltas preserve `context.key` and publish at most once per animation frame when requested.
|
|
251
257
|
6. The keyed renderer consumes `node.data` and constrained Location hooks only; it does not scan the Session event window, Contexts, or Chat Nodes.
|
|
252
258
|
7. Scalar and packed Assistant history produce the same final State, timing boundaries, and target snapshot, while one packed run remains one Match through replace, prepend, Location replay, and registry rebuild.
|
|
259
|
+
8. Creating a target source performs no builder work; explicit selection or the first subscription performs one complete replacement, later updates reach every active target, and repeated activation performs no replacement.
|
|
253
260
|
|
|
254
261
|
Use [`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) for streaming and interruption, [`inbox.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/inbox.ts) plus [`message.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/message.ts) for predecessor queries, and [`packages/client/ui-deliverables`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/client/ui-deliverables) for a Definition that publishes Turn data without creating its own Node.
|
|
@@ -20,7 +20,7 @@ A turn flows through the six packages in one loop: the driver in [`agent-loop`](
|
|
|
20
20
|
| `agent-loop/` | The concrete driver implementing the public `Agent` contract (`ctx.agentLoop`) | this page |
|
|
21
21
|
| `scope/` | The scoped-registration primitive the registries and loop build per-agent scoping on | [scope.md](./scope.md) |
|
|
22
22
|
|
|
23
|
-
`scope/` is the one non-service package: a dependency-free library (`createScope`/`scopeOf`/`scopeTarget`) that sits below `session/` and `system-prompt/` in the module graph precisely so they can consume it without a cycle. `agent-loop` is the one concrete implementation of the public `Agent` contract and lives here because it is the harness's default product loop; it runs each driver inside `ctx.agents.withInitiator()`. Extension plugins depend on `agent` — including when they need the initiating Agent — and never on `agent-loop` directly, so the loop stays swappable.
|
|
23
|
+
`scope/` is the one non-service package: a dependency-free library (`createScope`/`scopeOf`/`scopeTarget`) that sits below `session/` and `system-prompt/` in the module graph precisely so they can consume it without a cycle. `agent-loop` is the one concrete implementation of the public `Agent` contract and lives here because it is the harness's default product loop; it runs each driver inside `ctx.agents.withInitiator()`. Extension plugins depend on `agent` — including when they need the initiating Agent — and never on `agent-loop` directly, so the loop stays swappable. [`dsh-base`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/base/README.md) is the default product composition, while [`dsh-sdk-minimal`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/sdk-minimal/README.md) declares a smaller standalone tree.
|
|
24
24
|
|
|
25
25
|
## Creation and ownership
|
|
26
26
|
|
|
@@ -49,7 +49,7 @@ interface AgentHandle {
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
`CreateAgentOptions` carries the shared identity and everything a fresh agent needs before publication: session metadata (`meta` — validated `cwd`, fork lineage,
|
|
52
|
+
`CreateAgentOptions` carries the shared identity and everything a fresh agent needs before publication: session metadata (`meta` — validated `cwd`, fork lineage, the `isSeeded` marker, origin classification, delegation depth, and `agentPreset`), the exact fork cut in sibling field `inheritedEventCount`, an optional `seed` replay prefix, per-agent `AgentOptions`, a creation-only cancellation `signal`, and `setup`. `ResumeAgentOptions` is the persisted-identity counterpart: `resumeSessionId`, `agentOptions`, `signal`, and `setup`. The `setup` callback (`AgentSetup`) composes the agent's scoped world while both ids are still unpublished — everything registered through `agentCtx` exists before `agent/created` and the first prompt assembly — and may return a synchronous commit invoked immediately before publication; a setup rejection, commit throw, or owner disposal rolls the transaction back without publishing either id.
|
|
53
53
|
|
|
54
54
|
`AgentFactory` is the creation interface behind the registry: the loop registers its factory via `ctx.agents.setFactory()`, so consumers use `ctx.agents` without depending on the concrete loop package. The exact `create`/`resume` signatures and rollback contracts are in the [generated section](#ctxagents--agentregistry) below.
|
|
55
55
|
|
|
@@ -155,6 +155,44 @@ interface Agent {
|
|
|
155
155
|
type AgentStatus = 'idle' | 'running'
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
+
```ts type-equiv
|
|
159
|
+
/** One process-local live assistant streaming publication. */
|
|
160
|
+
type AssistantStreamFrame =
|
|
161
|
+
| {
|
|
162
|
+
readonly type: 'start'
|
|
163
|
+
readonly attemptId: LlmAttemptId
|
|
164
|
+
/** Monotone within one attached Agent lifecycle; replacement restarts at 1. */
|
|
165
|
+
readonly revision: number
|
|
166
|
+
readonly turn: number
|
|
167
|
+
readonly step: number
|
|
168
|
+
}
|
|
169
|
+
| {
|
|
170
|
+
readonly type: 'chunk'
|
|
171
|
+
readonly attemptId: LlmAttemptId
|
|
172
|
+
readonly revision: number
|
|
173
|
+
/** Dense zero-based position within the attempt. */
|
|
174
|
+
readonly index: number
|
|
175
|
+
/** Safe-integer timestamp reused by the durable embedded stream. */
|
|
176
|
+
readonly time: number
|
|
177
|
+
readonly chunk: StreamChunk
|
|
178
|
+
}
|
|
179
|
+
| {
|
|
180
|
+
readonly type: 'end'
|
|
181
|
+
readonly attemptId: LlmAttemptId
|
|
182
|
+
readonly revision: number
|
|
183
|
+
/** Number of chunk frames emitted by this attempt. */
|
|
184
|
+
readonly index: number
|
|
185
|
+
/** Durable settlement committed before this notification, or live abandonment without one. */
|
|
186
|
+
readonly outcome:
|
|
187
|
+
| {
|
|
188
|
+
readonly kind: 'committed'
|
|
189
|
+
readonly eventType: 'assistant/message' | 'assistant/attempt'
|
|
190
|
+
readonly seq: SessionSeq
|
|
191
|
+
}
|
|
192
|
+
| { readonly kind: 'abandoned' }
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
158
196
|
`running` describes the driver-wide drain interval and may span consecutive queued turns; it does not prove a turn is still open. Disposal removes the agent from the registry and emits `agent/disposed`; it is not a terminal status value. `followup()` returns no handle: its `MessageId` identifies durable inbox insertion, claim, and discard facts, not a later assistant output or turn ending. `whenIdle()` observes the whole agent, so callers may call a receipt-to-idle interval a run only when they explicitly own that interval ([decision](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md)).
|
|
159
197
|
|
|
160
198
|
```ts type-equiv
|
|
@@ -255,7 +293,7 @@ type SessionStartSource = 'startup' | 'resume' | 'clear' | 'compact'
|
|
|
255
293
|
|
|
256
294
|
A `Session` is an **append-only log** of typed `SessionEvent`s — the single source of truth. The LLM message history is *derived* from the log (`deriveMessages()`), not stored separately. Every entry carries a monotonic `seq`, a `time`, and a `type`-discriminated `data` payload; surface variants may also list cited earlier events in `sourceEventSeqs` and carry a `surfaceOp`.
|
|
257
295
|
|
|
258
|
-
The `SessionEvent` envelope's exact conditional fields, the twelve core event variants (`turn/start`, `turn/end`, `step/start`, `step/end`, `user/message`, `assistant/
|
|
296
|
+
The `SessionEvent` envelope's exact conditional fields, the twelve core event variants (`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`), the `deriveMessages()` projection rules, the `TurnEndReason` reasons, and the execution-enclosure and standalone-event rules are on **[session.md](./session.md)**. How the log is made durable — the `SessionPersistence` interface, JSONL provider, `session/flush` checkpoint, crash recovery, and `SessionHeader` — is on **[persistence.md](./persistence.md)**.
|
|
259
297
|
|
|
260
298
|
## `ToolDefinition`
|
|
261
299
|
|
|
@@ -304,9 +342,9 @@ Two large discriminated unions are the ones consumers `switch` over most: **`Str
|
|
|
304
342
|
|
|
305
343
|
### Branded IDs
|
|
306
344
|
|
|
307
|
-
IDs passed between packages are **branded** — structurally strings, but non-interchangeable at the type level (a `SessionId` cannot be passed where a `ToolCallId` is expected). Construction
|
|
345
|
+
IDs passed between packages are **branded** — structurally strings, but non-interchangeable at the type level (a `SessionId` cannot be passed where a `ToolCallId` is expected). Construction uses the shared `brandString<T>()` helper or an owner-defined validating factory; comparison, logging, and JSON behave as ordinary strings.
|
|
308
346
|
|
|
309
|
-
The `Branded<B>` primitive
|
|
347
|
+
The `Branded<B>` primitive and stateless constructor live in [dsh-brand](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/util/brand), which has no harness capability dependency. `brandString<T>()` applies a compile-time-only string brand.
|
|
310
348
|
|
|
311
349
|
Source: [`packages/util/brand/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/util/brand/src/index.ts)
|
|
312
350
|
|
|
@@ -359,13 +397,14 @@ Concrete agent factory and driver service.
|
|
|
359
397
|
/**
|
|
360
398
|
* Create an agent and session under one caller-supplied identity, owned by
|
|
361
399
|
* the accessing fiber. Constructor-driven config calls mint a fresh combined
|
|
362
|
-
* id before entering this boundary.
|
|
400
|
+
* id before entering this boundary. When a persistence backend is mounted,
|
|
401
|
+
* the session's durable identity and any seed are stored before publication.
|
|
363
402
|
* @param id - shared agent/session identity.
|
|
364
403
|
* @param options - concrete loop options.
|
|
365
404
|
* @param meta - optional fresh-session workspace metadata.
|
|
366
405
|
* @returns the published running agent.
|
|
367
406
|
*/
|
|
368
|
-
create(id: SessionId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): Agent
|
|
407
|
+
async create(id: SessionId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): Promise<Agent>
|
|
369
408
|
|
|
370
409
|
/**
|
|
371
410
|
* Create an owned agent on a caller-supplied session id.
|
|
@@ -413,6 +452,25 @@ async list(): Promise<AgentPreset[]>
|
|
|
413
452
|
*/
|
|
414
453
|
@Remote('list') async remoteExportList(): Promise<AgentPresetRoster>
|
|
415
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Every preset's composition as flattened plugin rows, for plugin-listing
|
|
457
|
+
* surfaces beside the roster's own picker.
|
|
458
|
+
*
|
|
459
|
+
* A preset with a live standing mount answers from its newest generation's
|
|
460
|
+
* Loader entries — the composition new sessions join — even when the file
|
|
461
|
+
* behind it has since been edited into an unreadable state: the mount is
|
|
462
|
+
* what sessions actually run, so the broken verdict only applies to a
|
|
463
|
+
* preset nothing composed. One never composed since boot answers from its
|
|
464
|
+
* file, with `!!js` disabled gates evaluated against the Loader context so
|
|
465
|
+
* both answers reflect the same host. Reading never mounts: an unmounted
|
|
466
|
+
* preset is parsed, not composed, so listing a preset's plugins cannot
|
|
467
|
+
* activate them early. A composition that stopped reading between
|
|
468
|
+
* discovery's health verdict and this read is reported broken with the
|
|
469
|
+
* raced reason rather than dropped.
|
|
470
|
+
* @returns one composition per roster preset, in roster order.
|
|
471
|
+
*/
|
|
472
|
+
async compositionInventory(): Promise<AgentPresetComposition[]>
|
|
473
|
+
|
|
416
474
|
/**
|
|
417
475
|
* Resolve one preset by id.
|
|
418
476
|
*
|
|
@@ -491,8 +549,8 @@ async read(id: string): Promise<string>
|
|
|
491
549
|
* One preset's composition text with the roster row it belongs to.
|
|
492
550
|
* @param agentPreset - the preset id.
|
|
493
551
|
* @returns the composition beside its trust and published metadata.
|
|
494
|
-
* @throws {
|
|
495
|
-
* `agent-preset
|
|
552
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty id, or
|
|
553
|
+
* `agent-preset/not-found` when no configured root supplies it.
|
|
496
554
|
*/
|
|
497
555
|
@Remote('read') async readDocument(agentPreset: string): Promise<AgentPresetDocument>
|
|
498
556
|
|
|
@@ -519,8 +577,8 @@ async copy(from: string, id: string, name?: string): Promise<void>
|
|
|
519
577
|
* @param id - the new preset id.
|
|
520
578
|
* @param name - the copy's optional display name.
|
|
521
579
|
* @returns once the copy is stored.
|
|
522
|
-
* @throws {
|
|
523
|
-
*
|
|
580
|
+
* @throws {RemoteError} with the corresponding stable preset code and
|
|
581
|
+
* details when the copy is refused.
|
|
524
582
|
*/
|
|
525
583
|
@Remote('copy') async remoteExportCopy(from: string, id: string, name?: string): Promise<void>
|
|
526
584
|
|
|
@@ -536,8 +594,8 @@ async remove(id: string): Promise<void>
|
|
|
536
594
|
* Delete one preset through the Remote API.
|
|
537
595
|
* @param id - the preset id.
|
|
538
596
|
* @returns once the preset is deleted.
|
|
539
|
-
* @throws {
|
|
540
|
-
*
|
|
597
|
+
* @throws {RemoteError} with the corresponding stable preset code and
|
|
598
|
+
* details when deletion is refused.
|
|
541
599
|
*/
|
|
542
600
|
@Remote('deletePreset') async remoteExportDelete(id: string): Promise<void>
|
|
543
601
|
|
|
@@ -588,8 +646,8 @@ async recompose(agentCtx: Context, id: string): Promise<AgentPreset>
|
|
|
588
646
|
* @param agent - the session's live agent, resolved from the wire identity.
|
|
589
647
|
* @param agentPreset - the preset to compose the agent from instead.
|
|
590
648
|
* @returns the preset id that was recorded.
|
|
591
|
-
* @throws {
|
|
592
|
-
* `agent-preset
|
|
649
|
+
* @throws {RemoteError} with `gateway/bad-request`, `agent-preset/locked`,
|
|
650
|
+
* `agent-preset/not-found`, or `agent-preset/invalid` when refused.
|
|
593
651
|
*/
|
|
594
652
|
@Remote('select') async select(agent: Agent, agentPreset: string): Promise<string>
|
|
595
653
|
|
|
@@ -787,6 +845,29 @@ Source: [`packages/core/agent/src/index.ts`](https://github.com/deepseek-ai/deep
|
|
|
787
845
|
|
|
788
846
|
### `agent/*` events
|
|
789
847
|
|
|
848
|
+
<a id="agentassistant-stream--emit"></a>
|
|
849
|
+
|
|
850
|
+
#### `agent/assistant-stream` — emit
|
|
851
|
+
|
|
852
|
+
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.
|
|
853
|
+
|
|
854
|
+
```ts cordis-catalog
|
|
855
|
+
/**
|
|
856
|
+
* Process-local assistant-stream publication. Chunk frames are transient;
|
|
857
|
+
* the loop appends one final v2 `assistant/message` or `assistant/attempt`
|
|
858
|
+
* with the same stream before a committed end frame.
|
|
859
|
+
* @param payload.agent - the agent whose attempt produced the frame.
|
|
860
|
+
* @param payload.frame - one ordered start, chunk, or end publication.
|
|
861
|
+
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
|
862
|
+
* @mode emit
|
|
863
|
+
*/
|
|
864
|
+
'agent/assistant-stream'(this: Scoped<Agent>, payload: { agent: Agent; frame: AssistantStreamFrame }): void
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
Types: [Scoped](./scope.md)
|
|
868
|
+
|
|
869
|
+
Source: [`packages/core/agent/src/runtime-types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent/src/runtime-types.ts)
|
|
870
|
+
|
|
790
871
|
<a id="agentcreated--emit"></a>
|
|
791
872
|
|
|
792
873
|
#### `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
|
## Service behavior
|
|
147
147
|
|
|
148
|
-
[`GoalService`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/src/index.ts) resolves creation defaults,
|
|
148
|
+
[`GoalService`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/src/index.ts) resolves creation defaults, reads strict replay from the optionally registered `goal` projection, enforces exact-live-agent identity and compare-and-set mutations, and emits contained `goal/changed` notifications. Its first dependent access fails if the projection registry or key is absent. The package [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/README.md) defines the callable API and model-visible contract.
|
|
149
149
|
|
|
150
150
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
151
151
|
|
|
@@ -19,7 +19,7 @@ One page per subsystem of the DeepSeek Harness: what it is, the data structures
|
|
|
19
19
|
| [todo.md](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/todo.md) | the todo package's whole-list item type, durable event ownership, projection, and open-turn invariant |
|
|
20
20
|
| [commands.md](./commands.md) | the human-command registry service: definitions, adapter discovery, direct invocation, results, and parsing views |
|
|
21
21
|
| [session.md](./session.md) | the full `SessionEventMap` variant catalog, `TurnEndReason`, `deriveMessages()`, execution enclosure, and standalone events |
|
|
22
|
-
| [persistence.md](./persistence.md) | the durability seam: `SessionPersistence`, JSONL
|
|
22
|
+
| [persistence.md](./persistence.md) | the durability seam: `SessionPersistence`, the JSONL provider, `session/flush`, crash recovery, `SessionHeader` |
|
|
23
23
|
| [settings.md](./settings.md) | the user-settings seam: `SettingsNamespace` registration, layered resolution (defaults → composition `base` → user document), owner scopes, hot commits |
|
|
24
24
|
| [credentials.md](./credentials.md) | the credential seam: `CredentialRef` references (never values) in configuration, per-operation resolution, UI-safe `CredentialInfo`, provider source layers |
|
|
25
25
|
| [session-query.md](./session-query.md) | logical records, bounded exact-event reads, relationship traces, semantic filters/documents, and full-text result pages |
|
|
@@ -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
|
-
The block interfaces (full fields in source): `TextBlock` (`text`), `ReasoningBlock` (thinking, distinct from visible text), `ImageBlock` (a durable [image attachment](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.md)), `ToolCallBlock` (`id: ToolCallId`, `name`, raw-JSON `arguments`), and `ToolResultBlock` (`toolCallId`, nested `content: ContentBlock[]`, `isError?`). `ContentBlock = ContentBlockMap[ContentBlockType]`. A new modality belongs in the merge-extensible map only when its adapter, UI, compaction, and durable replay paths honor it.
|
|
35
|
+
The block interfaces (full fields in source): `TextBlock` (`text`), `ReasoningBlock` (thinking, distinct from visible text), `ImageBlock` (a durable [image attachment](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.md)), `FileBlock` (a durable verbatim [file attachment](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.md) that request assembly projects to handle text for every route), `ToolCallBlock` (`id: ToolCallId`, `name`, raw-JSON `arguments`), and `ToolResultBlock` (`toolCallId`, nested `content: ContentBlock[]`, `isError?`). `ContentBlock = ContentBlockMap[ContentBlockType]`. A new modality belongs in the merge-extensible map only when its adapter, UI, compaction, and durable replay paths honor it.
|
|
35
36
|
|
|
36
37
|
Image access belongs to request serialization rather than the durable attachment or deterministic request-image version. `resolveImageAttachmentAccess()` combines the attachment provider's optional host object path with a mapping supplied by the consumer for the current tool execution filesystem. The result is available only for that request and does not participate in `variantId`.
|
|
37
38
|
|
|
@@ -219,6 +220,16 @@ type StreamChunk =
|
|
|
219
220
|
}
|
|
220
221
|
```
|
|
221
222
|
|
|
223
|
+
<a id="compact-assistant-streams"></a>
|
|
224
|
+
|
|
225
|
+
## Compact Assistant streams
|
|
226
|
+
|
|
227
|
+
`AssistantStreamAccumulator` pairs each `StreamChunk` with its original safe-integer timestamp and produces `AssistantStreamRecord[]`. Consecutive text, reasoning, or tool-argument deltas for the same block become one record with `time0`, exact timestamp gaps, and one array entry per original delta; every other chunk stays a timestamped raw record. This representation removes repeated event envelopes without joining token boundaries or dropping terminal, usage, block, failure, or replay facts.
|
|
228
|
+
|
|
229
|
+
`snapshot()` returns a detached immutable stream. `expandAssistantStream()` strictly checks record keys, member counts, indexes, timestamps, tool-call identity, and lossless JSON before recreating the exact timed chunk sequence. The Session log embeds this stream in `assistant/message` for a surface result or `assistant/attempt` for an attempt with no surface message.
|
|
230
|
+
|
|
231
|
+
Process-local `agent/assistant-stream` frames carry live presentation. Durable replay, telemetry, token accounting, and historical UI assembly expand the embedded settlement instead of treating live frames as persisted facts.
|
|
232
|
+
|
|
222
233
|
## `LlmFailure`
|
|
223
234
|
|
|
224
235
|
Every thrown or in-band final-adapter failure normalizes to one serializable provider-neutral payload. `providerRetryAfterMs` is a validated positive delay requested by the provider, not a retry decision; `ProviderRequestId` is an opaque branded string for diagnostics.
|
|
@@ -283,7 +294,7 @@ Every adapter MUST obey these, and every consumer may rely on them:
|
|
|
283
294
|
|
|
284
295
|
- **`usage` before `finish`, nothing after `finish`.** Defer both to the provider's end-of-stream marker so a trailing usage-only chunk can't violate the ordering.
|
|
285
296
|
- **Tool-call `arguments` stay raw JSON strings end-to-end.** Partial fragments stream via `argumentsDelta`; a provider that hands back parsed objects re-stringifies at `block-end`.
|
|
286
|
-
- **Two sanctioned error paths, one `LlmFailure` type.** A failure may either THROW from `stream()` (transport/protocol errors) **or** end the stream with `finish {kind:'error'|'aborted', failure}` (provider in-band errors, for adapters that can't throw mid-stream). `LlmError.failure` carries the same `LlmFailure`. After the call selects its adapter, the stream preserves the exact thrown `Error` object and associates immutable facts plus the serving registration's immutable retry policy with that call; the agent loop closes the failed step and offers the error, facts, immutable prior-retried facts, serving policy, and turn signal to `agent/request-error`. A handling listener returns `{ kind: 'retry' }` after its awaited repair; absent recovery the structured failure becomes the turn error, and no
|
|
297
|
+
- **Two sanctioned error paths, one `LlmFailure` type.** A failure may either THROW from `stream()` (transport/protocol errors) **or** end the stream with `finish {kind:'error'|'aborted', failure}` (provider in-band errors, for adapters that can't throw mid-stream). `LlmError.failure` carries the same `LlmFailure`. After the call selects its adapter, the stream preserves the exact thrown `Error` object and associates immutable facts plus the serving registration's immutable retry policy with that call; the agent loop commits the attempt stream as `assistant/attempt`, closes the failed step, and offers the error, facts, immutable prior-retried facts, serving policy, and turn signal to `agent/request-error`. A handling listener returns `{ kind: 'retry' }` after its awaited repair; absent recovery the structured failure becomes the turn error, and no surface Assistant message or tool side effect is committed for that attempt.
|
|
287
298
|
- **One adapter call is one provider attempt.** Adapters disable library retries. Agent-level recovery opens another durable numbered turn; direct `ctx.llm.stream()` callers remain single-attempt.
|
|
288
299
|
- **Provider stalls are bounded at the transport.** Both shipping remote adapters expose positive finite `streamIdleTimeoutMs` with a five-minute default. The watchdog arms only while iterator `next()` is outstanding, uses one stable signal for the whole request, maps its own expiry to `TIMEOUT`, and keeps an earlier caller abort as `ABORTED`.
|
|
289
300
|
- **Context overflow has one canonical code.** Both DeepSeek adapters classify explicit provider detail through `isContextWindowExceededError()` and surface `CONTEXT_WINDOW_EXCEEDED`, whether the failure arrives as a thrown HTTP `LlmError` or an in-band finish error. Consumers route on the code, never provider text.
|
|
@@ -932,7 +943,7 @@ async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, sig
|
|
|
932
943
|
* @param request - endpoint, protocol, and one-shot credential to use.
|
|
933
944
|
* @param signal - caller cancellation supplied by the Remote carrier.
|
|
934
945
|
* @returns advertised models in endpoint order.
|
|
935
|
-
* @throws
|
|
946
|
+
* @throws RemoteError with `llm/model-discovery-rejected` when discovery refuses or fails.
|
|
936
947
|
*/
|
|
937
948
|
@Remote('discoverModels') async remoteDiscoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, signal: AbortSignal, ): Promise<LlmDiscoveredModel[]>
|
|
938
949
|
|
|
@@ -954,6 +965,14 @@ providerRetryPolicy(provider: string): ResolvedRetryPolicy
|
|
|
954
965
|
*/
|
|
955
966
|
imageRequestPricing(provider: string, model: string): LlmImageRequestPricing | undefined
|
|
956
967
|
|
|
968
|
+
/**
|
|
969
|
+
* Resolve the exact text one durable file occurrence contributes to every
|
|
970
|
+
* provider request in the current execution environment.
|
|
971
|
+
* @param ref - durable verbatim file reference from model history.
|
|
972
|
+
* @returns the same deterministic handle text used at adapter dispatch.
|
|
973
|
+
*/
|
|
974
|
+
fileRequestText(ref: FileAttachmentRef): string
|
|
975
|
+
|
|
957
976
|
/**
|
|
958
977
|
* Discover models advertised by one registered provider. Catalog membership
|
|
959
978
|
* is advisory and never changes routing or request validation.
|
|
@@ -1009,6 +1028,8 @@ async prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise<Prepared
|
|
|
1009
1028
|
stream(options: GenerateOptions): AsyncIterable<StreamChunk>
|
|
1010
1029
|
```
|
|
1011
1030
|
|
|
1031
|
+
Types: [FileAttachmentRef](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.md)
|
|
1032
|
+
|
|
1012
1033
|
Source: [`packages/llm/llm/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/index.ts)
|
|
1013
1034
|
|
|
1014
1035
|
<a id="llm-events"></a>
|
|
@@ -48,7 +48,7 @@ The service requires a confining `ctx.shell` executor and `ctx.approval`, and mi
|
|
|
48
48
|
|
|
49
49
|
## Current preset and the derived `custom`
|
|
50
50
|
|
|
51
|
-
`current(
|
|
51
|
+
`current(session)` derives the effective preset from the optionally registered `permissions` projection. The unit folds the session's sandbox mode, approval policy, and recorded selection; values absent within that state fall back to the executor's configured mode and the approval service config, then `ask`. A missing registry or projection key fails explicitly. The service prefers a still-matching selection, then the first matching table entry in declaration order, and otherwise returns `CUSTOM_PRESET` (`'custom'`). `custom` is derived-only: clients may display it as the current value, but it is never a switch target or an event payload.
|
|
52
52
|
|
|
53
53
|
`names` lists the switchable presets in table declaration order; `optionOf(name)` builds the option a client renders for a table key (label falls back to the key) or for `custom`, and throws for any other name.
|
|
54
54
|
|
|
@@ -68,7 +68,7 @@ interface PresetOption {
|
|
|
68
68
|
|
|
69
69
|
`set(session, name)` resolves the preset (unknown names throw), appends a log-only `permission/preset` event unless `name` is already the effective preset, then writes each knob through its own setter — `setSandboxMode` from [dsh-sandbox-policy](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/sandbox/sandbox-policy) and `setApprovalPolicy` from [dsh-user-approval](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/interaction/user-approval) — only when that knob's effective value changes. The selection event precedes the knob events in the same turn, and re-selecting the effective preset appends nothing.
|
|
70
70
|
|
|
71
|
-
`permission/preset` is durable, log-only user intent: it stays out of the model transcript (the knob events own the model-visible consequences through their consumers), and it exists so `current()` can preserve WHICH preset the user chose when two presets share a bundle
|
|
71
|
+
`permission/preset` is durable, log-only user intent: it stays out of the model transcript (the knob events own the model-visible consequences through their consumers), and it exists so `current()` can preserve WHICH preset the user chose when two presets share a bundle. The `permissions` projection folds that selection with both knob events and retains the `session/end-seed` boundary used to distinguish a restored empty seed from a fresh session; replay needs no catch-up state or raw-log rescan. The complete event declaration is in the [persistence log event catalog](../persistence-catalog.md); the method signatures are in the generated [service catalog](#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 -->
|