dsh-plugin-dev-kb 1.0.8 → 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 +21 -0
- package/README.en.md +6 -6
- package/README.md +6 -6
- package/kb/INDEX.md +21 -5
- package/kb/README.md +11 -10
- package/kb/extra/AGENTS.md +4 -4
- 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/cookbook/adding-a-vendored-package.md +2 -2
- package/kb/extra/cookbook/adding-a-vendored-package.zh.md +2 -2
- package/kb/extra/deepseek-llm-api-wire-extensions.md +163 -0
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +163 -0
- package/kb/extra/development.md +8 -14
- package/kb/extra/development.zh.md +8 -14
- package/kb/extra/event-producer-consumer.md +55 -48
- package/kb/extra/event-producer-consumer.zh.md +58 -51
- package/kb/extra/glossary.md +1 -1
- package/kb/extra/glossary.zh.md +1 -1
- package/kb/extra/graph-atlas.md +0 -2
- package/kb/extra/graph-atlas.zh.md +0 -2
- package/kb/extra/i18n/README.md +4 -4
- package/kb/extra/i18n/README.zh.md +4 -4
- package/kb/extra/i18n/style-samples.md +2 -2
- package/kb/extra/module-graph.md +646 -926
- package/kb/extra/module-graph.zh.md +648 -928
- package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +2 -2
- package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +2 -2
- package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +2 -2
- package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +2 -2
- package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +2 -2
- package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +2 -2
- package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +1 -1
- package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +1 -1
- package/kb/extra/rescope.md +2 -2
- package/kb/extra/rescope.zh.md +2 -2
- package/kb/extra/subsystems/agent-team.md +28 -4
- package/kb/extra/subsystems/agent-team.zh.md +28 -4
- package/kb/extra/subsystems/attachment.md +168 -7
- package/kb/extra/subsystems/attachment.zh.md +168 -7
- package/kb/extra/subsystems/extensions.md +18 -0
- package/kb/extra/subsystems/extensions.zh.md +18 -0
- package/kb/extra/subsystems/feedback.md +4 -4
- package/kb/extra/subsystems/feedback.zh.md +4 -4
- package/kb/extra/subsystems/todo.md +32 -0
- package/kb/extra/subsystems/todo.zh.md +32 -0
- package/kb/extra/subsystems/webhook.md +70 -0
- package/kb/extra/subsystems/webhook.zh.md +70 -0
- package/kb/extra/testing.md +15 -10
- package/kb/extra/testing.zh.md +13 -8
- package/kb/extra/web-styling.md +4 -0
- package/kb/extra/web-styling.zh.md +4 -0
- package/kb/meta/search-index.json +309 -177
- package/kb/meta/site-pages.txt +183 -167
- package/kb/meta/source.json +5 -5
- package/kb/meta/topics.md +14 -6
- package/kb/site/develop/basic/publish.md +2 -2
- package/kb/site/develop/basic/tool.md +1 -1
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +5 -4
- package/kb/site/develop/framework/events.md +1 -1
- package/kb/site/develop/practice/dynamic-cordis.md +17 -0
- package/kb/site/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/develop/basic/publish.md +2 -2
- package/kb/site/en/develop/basic/tool.md +1 -1
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +5 -4
- package/kb/site/en/develop/framework/events.md +1 -1
- package/kb/site/en/develop/practice/dynamic-cordis.md +17 -0
- package/kb/site/en/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/guide/github-review.md +104 -0
- package/kb/site/en/guide/mcp-memory.md +103 -0
- package/kb/site/en/guide/network-proxy.md +87 -0
- package/kb/site/en/guide/providers.md +70 -17
- package/kb/site/en/guide/python-sdk.md +80 -34
- package/kb/site/en/guide/schedule.md +23 -0
- package/kb/site/en/reference/agent-lifecycle.md +6 -4
- package/kb/{extra → site/en/reference}/api-gateway.md +12 -10
- package/kb/site/en/reference/capability-seams.md +128 -73
- package/kb/site/en/reference/config-catalog.md +481 -360
- package/kb/site/en/reference/cookbook/adding-a-package.md +3 -4
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +12 -10
- package/kb/site/en/reference/cookbook/adding-a-tool.md +11 -4
- package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +1 -1
- package/kb/site/en/reference/cookbook/extension-cookbook.md +20 -17
- package/kb/site/en/reference/cordis-api/inherited.md +1 -1
- package/kb/site/en/reference/cordis-primer.md +2 -1
- package/kb/site/en/reference/index.md +30 -11
- package/kb/site/en/reference/persistence-catalog.md +148 -80
- package/kb/site/en/reference/subsystems/approval.md +10 -10
- package/kb/site/en/reference/subsystems/client-modules.md +58 -16
- package/kb/site/en/reference/subsystems/code-runtime.md +10 -6
- package/kb/site/en/reference/subsystems/commands.md +25 -16
- package/kb/site/en/reference/subsystems/compaction.md +11 -11
- package/kb/site/en/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
- package/kb/site/en/reference/subsystems/core.md +156 -17
- package/kb/site/en/reference/subsystems/credentials.md +44 -3
- package/kb/site/en/reference/subsystems/filesystem.md +12 -2
- package/kb/site/en/reference/subsystems/goal.md +1 -1
- package/kb/site/en/reference/subsystems/index.md +7 -2
- package/kb/site/en/reference/subsystems/jobs.md +1 -1
- package/kb/site/en/reference/subsystems/llm-streaming.md +154 -12
- package/kb/site/en/reference/subsystems/permission-presets.md +6 -6
- package/kb/site/en/reference/subsystems/persistence.md +185 -175
- package/kb/site/en/reference/subsystems/plan.md +2 -2
- 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 +115 -48
- package/kb/site/en/reference/subsystems/session-query.md +28 -14
- package/kb/site/en/reference/subsystems/session-reference.md +53 -8
- package/kb/site/en/reference/subsystems/session-telemetry.md +8 -8
- package/kb/site/en/reference/subsystems/session-title.md +6 -6
- package/kb/site/en/reference/subsystems/session.md +401 -99
- package/kb/site/en/reference/subsystems/settings.md +101 -6
- package/kb/site/en/reference/subsystems/skills.md +23 -0
- package/kb/site/en/reference/subsystems/slots.md +178 -0
- package/kb/site/en/reference/subsystems/spill.md +2 -2
- package/kb/site/en/reference/subsystems/storage.md +34 -3
- package/kb/site/en/reference/subsystems/subagent.md +122 -109
- package/kb/site/en/reference/subsystems/system-prompt.md +17 -4
- package/kb/site/en/reference/subsystems/token-meter.md +27 -12
- package/kb/site/en/reference/subsystems/tools.md +39 -39
- package/kb/site/en/reference/subsystems/typert.md +62 -55
- package/kb/site/en/reference/subsystems/user-questions.md +33 -33
- package/kb/site/en/reference/subsystems/web-client.md +98 -0
- package/kb/site/en/reference/subsystems/web-server.md +11 -5
- package/kb/site/en/reference/subsystems/web.md +7 -1
- package/kb/site/en/reference/subsystems/workspace.md +102 -9
- package/kb/site/en/reference/tool-catalog.md +86 -82
- package/kb/site/en/reference/tool-execution-pipeline.md +1 -1
- package/kb/site/guide/github-review.md +104 -0
- package/kb/site/guide/mcp-memory.md +103 -0
- package/kb/site/guide/network-proxy.md +87 -0
- package/kb/site/guide/providers.md +70 -17
- package/kb/site/guide/python-sdk.md +87 -41
- package/kb/site/guide/schedule.md +23 -0
- package/kb/site/reference/agent-lifecycle.md +6 -4
- package/kb/{extra/api-gateway.zh.md → site/reference/api-gateway.md} +12 -10
- package/kb/site/reference/capability-seams.md +128 -73
- package/kb/site/reference/config-catalog.md +481 -360
- package/kb/site/reference/cookbook/adding-a-package.md +3 -4
- package/kb/site/reference/cookbook/adding-a-settings-card.md +12 -10
- package/kb/site/reference/cookbook/adding-a-tool.md +11 -4
- package/kb/site/reference/cookbook/adding-an-llm-adapter.md +1 -1
- package/kb/site/reference/cookbook/extension-cookbook.md +20 -17
- package/kb/site/reference/cordis-api/inherited.md +1 -1
- package/kb/site/reference/cordis-primer.md +2 -1
- package/kb/site/reference/index.md +30 -11
- package/kb/site/reference/persistence-catalog.md +148 -80
- package/kb/site/reference/subsystems/approval.md +10 -10
- package/kb/site/reference/subsystems/client-modules.md +58 -16
- package/kb/site/reference/subsystems/code-runtime.md +10 -6
- package/kb/site/reference/subsystems/commands.md +25 -16
- package/kb/site/reference/subsystems/compaction.md +11 -11
- package/kb/site/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
- package/kb/site/reference/subsystems/core.md +156 -17
- package/kb/site/reference/subsystems/credentials.md +44 -3
- package/kb/site/reference/subsystems/filesystem.md +12 -2
- package/kb/site/reference/subsystems/goal.md +1 -1
- package/kb/site/reference/subsystems/index.md +7 -2
- package/kb/site/reference/subsystems/jobs.md +1 -1
- package/kb/site/reference/subsystems/llm-streaming.md +154 -12
- package/kb/site/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/reference/subsystems/persistence.md +184 -174
- package/kb/site/reference/subsystems/plan.md +2 -2
- package/kb/site/reference/subsystems/schedule.md +9 -3
- package/kb/site/reference/subsystems/session-projection.md +115 -48
- package/kb/site/reference/subsystems/session-query.md +28 -14
- package/kb/site/reference/subsystems/session-reference.md +53 -8
- package/kb/site/reference/subsystems/session-telemetry.md +8 -8
- package/kb/site/reference/subsystems/session-title.md +6 -6
- package/kb/site/reference/subsystems/session.md +401 -99
- package/kb/site/reference/subsystems/settings.md +101 -6
- package/kb/site/reference/subsystems/skills.md +23 -0
- package/kb/site/reference/subsystems/slots.md +178 -0
- package/kb/site/reference/subsystems/spill.md +2 -2
- package/kb/site/reference/subsystems/storage.md +34 -3
- package/kb/site/reference/subsystems/subagent.md +122 -109
- package/kb/site/reference/subsystems/system-prompt.md +17 -4
- package/kb/site/reference/subsystems/token-meter.md +27 -12
- package/kb/site/reference/subsystems/tools.md +39 -39
- package/kb/site/reference/subsystems/typert.md +62 -55
- package/kb/site/reference/subsystems/user-questions.md +33 -33
- package/kb/site/reference/subsystems/web-client.md +98 -0
- package/kb/site/reference/subsystems/web-server.md +11 -5
- package/kb/site/reference/subsystems/web.md +7 -1
- package/kb/site/reference/subsystems/workspace.md +102 -9
- package/kb/site/reference/tool-catalog.md +85 -81
- package/kb/site/reference/tool-execution-pipeline.md +1 -1
- package/package.json +2 -2
- package/skills/dsh-plugin-dev-kb.md +8 -6
|
@@ -26,12 +26,25 @@ 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:
|
|
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.
|
|
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`.
|
|
38
|
+
|
|
39
|
+
Source: [`packages/llm/llm/src/content.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/content.ts)
|
|
40
|
+
|
|
41
|
+
```ts type-equiv
|
|
42
|
+
/** Execution-world path that model tools can use to read one normalized attachment. */
|
|
43
|
+
interface ImageAttachmentAccess {
|
|
44
|
+
/** Absolute path to immutable normalized bytes; callers must treat it as read-only. */
|
|
45
|
+
readonlyPath: string
|
|
46
|
+
}
|
|
47
|
+
```
|
|
35
48
|
|
|
36
49
|
Source: [`packages/llm/llm/src/message.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/message.ts)
|
|
37
50
|
|
|
@@ -196,7 +209,7 @@ type StreamChunk =
|
|
|
196
209
|
| { type: 'block-start'; index: number; blockType: ContentBlockType }
|
|
197
210
|
| { type: 'text-delta'; index: number; text: string }
|
|
198
211
|
| { type: 'reasoning-delta'; index: number; text: string }
|
|
199
|
-
| { type: 'tool-call-delta'; index: number; id:
|
|
212
|
+
| { type: 'tool-call-delta'; index: number; id: ToolCallId; name?: string; argumentsDelta: string }
|
|
200
213
|
| { type: 'block-end'; index: number; block: ContentBlock }
|
|
201
214
|
| { type: 'usage'; usage: TokenUsage }
|
|
202
215
|
| {
|
|
@@ -207,6 +220,16 @@ type StreamChunk =
|
|
|
207
220
|
}
|
|
208
221
|
```
|
|
209
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
|
+
|
|
210
233
|
## `LlmFailure`
|
|
211
234
|
|
|
212
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.
|
|
@@ -227,13 +250,51 @@ interface LlmFailure {
|
|
|
227
250
|
}
|
|
228
251
|
```
|
|
229
252
|
|
|
253
|
+
## Request-image pricing
|
|
254
|
+
|
|
255
|
+
An adapter whose provider charges visual tokens for request images declares per-route pricing by overriding `LlmAdapter.imageRequestPricing`, and `ctx.llm.imageRequestPricing(provider, model)` resolves it synchronously for consumers. The token meter resolves the routed model's pricing on every measurement so compaction pressure, retention, and range selection price image history as the routed request actually sends it; the DeepSeek adapter reproduces its own request projection (per-model pixel budget, oldest-first offload) and prices retained images with the published v4 vision accounting, while provider usage remains the authoritative anchor for completed requests.
|
|
256
|
+
|
|
257
|
+
```ts type-equiv
|
|
258
|
+
/**
|
|
259
|
+
* Request price of one ordered image occurrence under one exact model route's
|
|
260
|
+
* request projection. Every occurrence resolves to the pair the wire actually
|
|
261
|
+
* carries: provider visual tokens for a retained image, plus the model-visible
|
|
262
|
+
* text sent with or instead of it (request-preview handle, offload placeholder,
|
|
263
|
+
* or text-only substitution). The caller prices `text` with its own text
|
|
264
|
+
* estimator so provider pricing never fixes a text tokenization.
|
|
265
|
+
*/
|
|
266
|
+
interface LlmImageRequestPrice {
|
|
267
|
+
/** Provider visual tokens for the retained request image; 0 when only text represents this occurrence. */
|
|
268
|
+
visualTokens: number
|
|
269
|
+
/** Model-visible text sent for this occurrence, to be priced by the caller's text estimator. */
|
|
270
|
+
text: string
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
```ts type-equiv
|
|
275
|
+
/**
|
|
276
|
+
* Provider-side request-image pricing for one exact model route. Implemented
|
|
277
|
+
* by adapters whose provider charges visual tokens; consumers (the token
|
|
278
|
+
* meter) resolve it synchronously per measurement, so implementations must not
|
|
279
|
+
* perform I/O.
|
|
280
|
+
*/
|
|
281
|
+
interface LlmImageRequestPricing {
|
|
282
|
+
/**
|
|
283
|
+
* Price every image occurrence of one request projection.
|
|
284
|
+
* @param images - durable image references in request order, one entry per occurrence.
|
|
285
|
+
* @returns one price per occurrence, aligned by index with `images`.
|
|
286
|
+
*/
|
|
287
|
+
priceImages(images: readonly ImageAttachmentRef[]): readonly LlmImageRequestPrice[]
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
230
291
|
## The adapter contract
|
|
231
292
|
|
|
232
293
|
Every adapter MUST obey these, and every consumer may rely on them:
|
|
233
294
|
|
|
234
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.
|
|
235
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`.
|
|
236
|
-
- **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.
|
|
237
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.
|
|
238
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`.
|
|
239
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.
|
|
@@ -269,7 +330,7 @@ interface AppIdentity {
|
|
|
269
330
|
|
|
270
331
|
## `TokenUsage`
|
|
271
332
|
|
|
272
|
-
Per-call token accounting. Counts are **disjoint**: `inputTokens` is uncached input only; cached input is reported separately, and billed input is the sum of the three. Adapters whose providers fold cache hits into a single prompt total (DeepSeek's `prompt_tokens`) subtract them back out. `reasoningTokens`, when present, is informational detail already included in `outputTokens`; totals must not add it again.
|
|
333
|
+
Per-call token accounting. Counts are **disjoint**: `inputTokens` is uncached input only; cached input is reported separately, and billed input is the sum of the three. Adapters whose providers fold cache hits into a single prompt total (DeepSeek's `prompt_tokens`) subtract them back out. Optional `totalTokens` is an exact aggregate prompt-plus-output count preserved from the provider or reconstructed from authoritative aggregate counters; adapters omit it when unavailable or inconsistent. `reasoningTokens`, when present, is informational detail already included in `outputTokens`; totals must not add it again.
|
|
273
334
|
|
|
274
335
|
```ts type-equiv
|
|
275
336
|
/**
|
|
@@ -283,6 +344,14 @@ Per-call token accounting. Counts are **disjoint**: `inputTokens` is uncached in
|
|
|
283
344
|
interface TokenUsage {
|
|
284
345
|
inputTokens: number
|
|
285
346
|
outputTokens: number
|
|
347
|
+
/**
|
|
348
|
+
* Exact full-call total including aggregate prompt and output tokens.
|
|
349
|
+
*
|
|
350
|
+
* Adapters preserve a provider total or derive it from authoritative
|
|
351
|
+
* aggregate prompt/output counters; they omit it when unavailable or
|
|
352
|
+
* inconsistent.
|
|
353
|
+
*/
|
|
354
|
+
totalTokens?: number
|
|
286
355
|
cacheReadTokens?: number
|
|
287
356
|
cacheWriteTokens?: number
|
|
288
357
|
reasoningTokens?: number
|
|
@@ -356,7 +425,7 @@ One model call is a fully-assembled `GenerateOptions`. The adapter answers with
|
|
|
356
425
|
|
|
357
426
|
Source: [`packages/llm/llm/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/types.ts)
|
|
358
427
|
|
|
359
|
-
Provider and model discovery uses small provider-neutral descriptors. A model catalog is advisory: routing still keys on a registered provider
|
|
428
|
+
Provider and model discovery uses small provider-neutral descriptors. A model catalog is advisory: routing still keys on a registered provider.
|
|
360
429
|
|
|
361
430
|
Registering an adapter returns a handle: the disposer, plus the atomic route replacement a plugin whose route set is user-configurable needs.
|
|
362
431
|
|
|
@@ -604,8 +673,6 @@ interface LlmModelDiscoveryRequest {
|
|
|
604
673
|
api?: string
|
|
605
674
|
/** Credential for this interrogation alone; the harness never stores it. */
|
|
606
675
|
apiKey?: string
|
|
607
|
-
/** Caller cancellation; implementations must settle promptly after it aborts. */
|
|
608
|
-
signal?: AbortSignal
|
|
609
676
|
}
|
|
610
677
|
```
|
|
611
678
|
|
|
@@ -665,6 +732,12 @@ interface LlmCallConfigAdapterDefaults {
|
|
|
665
732
|
}
|
|
666
733
|
```
|
|
667
734
|
|
|
735
|
+
## Official DeepSeek request extensions
|
|
736
|
+
|
|
737
|
+
`ctx.deepseekLlmApiExtensions` is the provider-specific registry for additive top-level fields on `deepseek-official` requests. Contributor plugins use `register(field, provider)` to claim one field; the adapter calls `prepare(request)` after serializing its base body and merges the returned fields before HTTP. The prepared `accept()` transaction runs after 2xx, so a contributor can commit delivery state without treating a transport or provider rejection as acceptance. Preparation, collision, and acceptance failures use `REQUEST_EXTENSION` and fail the model request.
|
|
738
|
+
|
|
739
|
+
The [wire reference](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/deepseek-llm-api-wire-extensions.md) defines the exact request headers, extension transaction, field versions, and receiver obligations. The shipped composition registers [`dsh_session_log`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-log-deepseek/README.md) as a lossless incremental canonical-log suffix and [`dsh_plugin_packages`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/plugin-package-inventory-deepseek/README.md) as the complete active Loader-backed package set. These fields remain outside model messages and are absent from the pi-ai adapter path.
|
|
740
|
+
|
|
668
741
|
## Service and provider contracts
|
|
669
742
|
|
|
670
743
|
`LlmAdapter` is the provider contract: subclass, implement `stream()`, and register one adapter instance with `ctx.llm.registerAdapter(providers, adapter)`. `GenerateOptions.provider` selects the registered adapter; `GenerateOptions.model` is passed to that adapter and need not be registered at lifecycle start. Duplicate provider routes fail atomically. Optional `providerRetryPolicy()` is captured per route with normal defaults, while `providerInfo()` and asynchronous `listModels()` feed `LlmRuntime.listProviders()` / `listModels()` with detached selector metadata. That catalog is advisory rather than a request whitelist: the adapter remains authoritative and may accept unlisted model ids. One asynchronous `resolveModel()` query returns exact model identity plus optional correctness-sensitive context capacity, an adapter-configured `defaultMaxTokens`, and ordered model-owned reasoning ids with an optional deployment default; absent fields mean unavailable metadata or provider-owned behavior, not invalid catalog membership. The resolver receives optional cancellation and must settle promptly after abort. `LlmRuntime.resolveModelInfo()` validates and detaches the aggregate. At the final adapter boundary, `resolveCallConfig()` materializes the output default only when `maxTokens` is absent and validates and materializes reasoning, so direct calls cannot bypass either configured behavior; direct dispatch captures one registration before awaiting that resolution. The agent loop instead uses `prepareCall()` to keep the same registration across model resolution, durable header logging, and dispatch, retain detached context metadata from that exact lookup, and report which config fields the adapter defaulted. Adapter lookup happens at the terminal continuation of the `llm/stream` waterfall, so a listener may short-circuit the call or route a mutable one-shot request before lookup. AgentLoop observes a request attempt once the outer waterfall returns a stream handle; that limited boundary does not prove a lazy terminal adapter was constructed or began provider I/O. The `block-start` / `block-end` `index` correlation and the assembler together mean an adapter only has to emit well-formed chunks — block reassembly is not each adapter's problem. [architecture.md](../index.md#turn-flow) shows where `ctx.llm.stream()` and the `llm/stream` waterfall sit in one turn.
|
|
@@ -713,6 +786,16 @@ declare abstract class LlmAdapter {
|
|
|
713
786
|
* @returns a resolved policy, or `undefined` to use the normal defaults.
|
|
714
787
|
*/
|
|
715
788
|
providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined;
|
|
789
|
+
/**
|
|
790
|
+
* Resolve provider-side request-image pricing for one exact model route.
|
|
791
|
+
* The default declares none, so consumers fall back to their own neutral
|
|
792
|
+
* estimate. Implementations must answer synchronously without I/O; the
|
|
793
|
+
* token meter resolves this per measurement.
|
|
794
|
+
* @param _provider - a route passed to `registerAdapter()` for this instance.
|
|
795
|
+
* @param _model - exact model id passed to {@link GenerateOptions.model}.
|
|
796
|
+
* @returns route-owned image pricing, or `undefined` when the route declares none.
|
|
797
|
+
*/
|
|
798
|
+
imageRequestPricing(_provider: string, _model: string): LlmImageRequestPricing | undefined;
|
|
716
799
|
/**
|
|
717
800
|
* List models this adapter can currently advertise for one owned provider.
|
|
718
801
|
* The result is advisory: an adapter may accept unlisted model ids, and
|
|
@@ -764,6 +847,33 @@ declare abstract class LlmAdapter {
|
|
|
764
847
|
|
|
765
848
|
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
|
766
849
|
|
|
850
|
+
<a id="ctxdeepseekllmapiextensions--deepseekllmapiextensionregistry"></a>
|
|
851
|
+
|
|
852
|
+
### `ctx.deepseekLlmApiExtensions` — `DeepSeekLlmApiExtensionRegistry`
|
|
853
|
+
|
|
854
|
+
Registry of independently owned top-level fields for official DeepSeek requests.
|
|
855
|
+
|
|
856
|
+
```ts cordis-catalog
|
|
857
|
+
/**
|
|
858
|
+
* Register the sole provider of one top-level request field. Registration is effect-scoped.
|
|
859
|
+
* @param field - declaration-merged field owned by the provider.
|
|
860
|
+
* @param provider - request-time field preparation and optional acceptance behavior.
|
|
861
|
+
* @returns disposer that releases the field.
|
|
862
|
+
*/
|
|
863
|
+
register<K extends keyof DeepSeekLlmApiExtensionMap>( field: K, provider: DeepSeekLlmApiExtensionProvider<DeepSeekLlmApiExtensionMap[K]>, ): () => Promise<void>
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Prepare every currently registered field from one immutable base request.
|
|
867
|
+
* Preparation failures reject before HTTP dispatch. Field values are cloned and frozen;
|
|
868
|
+
* providers retain no mutable alias to the outgoing request.
|
|
869
|
+
* @param request - exact serialized request facts before extension fields.
|
|
870
|
+
* @returns detached fields and their idempotent joint acceptance transaction.
|
|
871
|
+
*/
|
|
872
|
+
async prepare(request: DeepSeekLlmApiExtensionRequest): Promise<PreparedDeepSeekLlmApiExtensions>
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
Source: [`packages/llm/deepseek-llm-api-extensions/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/deepseek-llm-api-extensions/src/index.ts)
|
|
876
|
+
|
|
767
877
|
<a id="ctxllm--llmruntime"></a>
|
|
768
878
|
|
|
769
879
|
### `ctx.llm` — `LlmRuntime`
|
|
@@ -785,7 +895,7 @@ registerAdapter(providers: string[], adapter: LlmAdapter): AdapterRegistrationHa
|
|
|
785
895
|
* Describe provider routes with a registered adapter.
|
|
786
896
|
* @returns detached provider metadata in registration order.
|
|
787
897
|
*/
|
|
788
|
-
listProviders(): LlmProviderInfo[]
|
|
898
|
+
@Remote listProviders(): LlmProviderInfo[]
|
|
789
899
|
|
|
790
900
|
/**
|
|
791
901
|
* Declare provider routes an adapter plugin can activate through
|
|
@@ -801,7 +911,7 @@ registerConfigurableProviders(entries: readonly LlmConfigurableProvider[]): Dire
|
|
|
801
911
|
* List every declared configurable provider, registered or dormant.
|
|
802
912
|
* @returns detached directory entries in declaration order.
|
|
803
913
|
*/
|
|
804
|
-
listConfigurableProviders(): LlmConfigurableProvider[]
|
|
914
|
+
@Remote listConfigurableProviders(): LlmConfigurableProvider[]
|
|
805
915
|
|
|
806
916
|
/**
|
|
807
917
|
* Offer to interrogate provider endpoints on behalf of the settings
|
|
@@ -810,10 +920,10 @@ listConfigurableProviders(): LlmConfigurableProvider[]
|
|
|
810
920
|
* directory, and because a provider being *added* has no route to name yet.
|
|
811
921
|
* Disposed with the fiber.
|
|
812
922
|
* @param settingsNs - the namespace whose profiles this discovery serves.
|
|
813
|
-
* @param discover - interrogates one endpoint
|
|
923
|
+
* @param discover - interrogates one endpoint and must honor the supplied signal.
|
|
814
924
|
* @returns the disposer that withdraws the offer.
|
|
815
925
|
*/
|
|
816
|
-
registerModelDiscovery( settingsNs: string, discover: (request: LlmModelDiscoveryRequest) => Promise<readonly LlmDiscoveredModel[]>, ): () => void
|
|
926
|
+
registerModelDiscovery( settingsNs: string, discover: ( request: LlmModelDiscoveryRequest, signal?: AbortSignal, ) => Promise<readonly LlmDiscoveredModel[]>, ): () => void
|
|
817
927
|
|
|
818
928
|
/**
|
|
819
929
|
* Interrogate one provider endpoint for the models it advertises. The
|
|
@@ -822,9 +932,20 @@ registerModelDiscovery( settingsNs: string, discover: (request: LlmModelDiscover
|
|
|
822
932
|
* candidate metadata a surface may offer for adoption.
|
|
823
933
|
* @param settingsNs - namespace whose registered discovery serves this draft.
|
|
824
934
|
* @param request - the endpoint, protocol, and one-shot credential to use.
|
|
935
|
+
* @param signal - caller cancellation.
|
|
825
936
|
* @returns the advertised models, deduplicated in endpoint order.
|
|
826
937
|
*/
|
|
827
|
-
async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, ): Promise<LlmDiscoveredModel[]>
|
|
938
|
+
async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, signal?: AbortSignal, ): Promise<LlmDiscoveredModel[]>
|
|
939
|
+
|
|
940
|
+
/**
|
|
941
|
+
* Remote adapter for one draft provider interrogation.
|
|
942
|
+
* @param settingsNs - namespace whose registered discovery serves this draft.
|
|
943
|
+
* @param request - endpoint, protocol, and one-shot credential to use.
|
|
944
|
+
* @param signal - caller cancellation supplied by the Remote carrier.
|
|
945
|
+
* @returns advertised models in endpoint order.
|
|
946
|
+
* @throws RemoteError with `llm/model-discovery-rejected` when discovery refuses or fails.
|
|
947
|
+
*/
|
|
948
|
+
@Remote('discoverModels') async remoteDiscoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, signal: AbortSignal, ): Promise<LlmDiscoveredModel[]>
|
|
828
949
|
|
|
829
950
|
/**
|
|
830
951
|
* Resolve the retry policy captured when one provider route was registered.
|
|
@@ -833,6 +954,25 @@ async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, ):
|
|
|
833
954
|
*/
|
|
834
955
|
providerRetryPolicy(provider: string): ResolvedRetryPolicy
|
|
835
956
|
|
|
957
|
+
/**
|
|
958
|
+
* Resolve provider-side request-image pricing for one exact route, or
|
|
959
|
+
* `undefined` when the provider is unregistered or declares none. Unknown
|
|
960
|
+
* providers degrade to `undefined` rather than throwing because callers
|
|
961
|
+
* price durable history whose route may no longer be mounted.
|
|
962
|
+
* @param provider - provider route named by a request header.
|
|
963
|
+
* @param model - exact model id named by the same header.
|
|
964
|
+
* @returns the owning adapter's image pricing for the route, when declared.
|
|
965
|
+
*/
|
|
966
|
+
imageRequestPricing(provider: string, model: string): LlmImageRequestPricing | undefined
|
|
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
|
+
|
|
836
976
|
/**
|
|
837
977
|
* Discover models advertised by one registered provider. Catalog membership
|
|
838
978
|
* is advisory and never changes routing or request validation.
|
|
@@ -888,6 +1028,8 @@ async prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise<Prepared
|
|
|
888
1028
|
stream(options: GenerateOptions): AsyncIterable<StreamChunk>
|
|
889
1029
|
```
|
|
890
1030
|
|
|
1031
|
+
Types: [FileAttachmentRef](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/attachment.md)
|
|
1032
|
+
|
|
891
1033
|
Source: [`packages/llm/llm/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/index.ts)
|
|
892
1034
|
|
|
893
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
|
|
|
@@ -66,9 +66,9 @@ interface PresetOption {
|
|
|
66
66
|
|
|
67
67
|
## Switching and the `permission/preset` event
|
|
68
68
|
|
|
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
|
|
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 -->
|