dsh-plugin-dev-kb 1.0.8 → 1.0.9
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 +11 -0
- package/README.en.md +6 -6
- package/README.md +6 -6
- package/kb/INDEX.md +19 -5
- package/kb/README.md +11 -10
- package/kb/extra/AGENTS.md +4 -4
- 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 +159 -0
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +159 -0
- package/kb/extra/development.md +8 -14
- package/kb/extra/development.zh.md +8 -14
- package/kb/extra/event-producer-consumer.md +47 -41
- package/kb/extra/event-producer-consumer.zh.md +47 -41
- 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/module-graph.md +680 -413
- package/kb/extra/module-graph.zh.md +681 -414
- 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 +24 -1
- package/kb/extra/subsystems/agent-team.zh.md +24 -1
- package/kb/extra/subsystems/attachment.md +12 -4
- package/kb/extra/subsystems/attachment.zh.md +12 -4
- package/kb/extra/subsystems/extensions.md +18 -0
- package/kb/extra/subsystems/extensions.zh.md +18 -0
- package/kb/extra/subsystems/feedback.md +2 -2
- package/kb/extra/subsystems/feedback.zh.md +2 -2
- 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 +11 -10
- package/kb/extra/testing.zh.md +8 -7
- package/kb/meta/search-index.json +269 -161
- package/kb/meta/site-pages.txt +182 -168
- 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 +4 -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 +3 -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 +4 -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 +3 -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/python-sdk.md +80 -34
- package/kb/site/en/guide/schedule.md +21 -0
- package/kb/site/en/reference/agent-lifecycle.md +1 -1
- package/kb/{extra → site/en/reference}/api-gateway.md +11 -9
- package/kb/site/en/reference/capability-seams.md +115 -67
- package/kb/site/en/reference/config-catalog.md +358 -164
- package/kb/site/en/reference/cookbook/adding-a-package.md +2 -2
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +2 -2
- 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 +6 -6
- 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 +19 -7
- package/kb/site/en/reference/persistence-catalog.md +91 -44
- 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 +3 -3
- package/kb/site/en/reference/subsystems/compaction.md +2 -2
- package/kb/site/en/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +43 -24
- package/kb/site/en/reference/subsystems/core.md +70 -12
- package/kb/site/en/reference/subsystems/credentials.md +43 -3
- package/kb/site/en/reference/subsystems/filesystem.md +12 -2
- package/kb/site/en/reference/subsystems/index.md +6 -1
- package/kb/site/en/reference/subsystems/jobs.md +1 -1
- package/kb/site/en/reference/subsystems/llm-streaming.md +132 -11
- package/kb/site/en/reference/subsystems/permission-presets.md +1 -1
- package/kb/site/en/reference/subsystems/persistence.md +22 -3
- package/kb/site/en/reference/subsystems/plan.md +1 -1
- package/kb/site/en/reference/subsystems/session-projection.md +74 -33
- package/kb/site/en/reference/subsystems/session-query.md +9 -1
- package/kb/site/en/reference/subsystems/session-reference.md +28 -7
- package/kb/site/en/reference/subsystems/session-telemetry.md +2 -3
- package/kb/site/en/reference/subsystems/session.md +260 -41
- package/kb/site/en/reference/subsystems/settings.md +78 -1
- package/kb/site/en/reference/subsystems/skills.md +23 -0
- package/kb/site/en/reference/subsystems/slots.md +177 -0
- package/kb/site/en/reference/subsystems/spill.md +2 -2
- package/kb/site/en/reference/subsystems/storage.md +9 -1
- package/kb/site/en/reference/subsystems/subagent.md +90 -23
- package/kb/site/en/reference/subsystems/system-prompt.md +4 -4
- package/kb/site/en/reference/subsystems/token-meter.md +25 -10
- package/kb/site/en/reference/subsystems/tools.md +39 -39
- package/kb/site/en/reference/subsystems/typert.md +44 -37
- 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 +95 -2
- package/kb/site/en/reference/tool-catalog.md +76 -18
- 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/python-sdk.md +87 -41
- package/kb/site/guide/schedule.md +21 -0
- package/kb/site/reference/agent-lifecycle.md +1 -1
- package/kb/{extra/api-gateway.zh.md → site/reference/api-gateway.md} +11 -9
- package/kb/site/reference/capability-seams.md +115 -67
- package/kb/site/reference/config-catalog.md +357 -163
- package/kb/site/reference/cookbook/adding-a-package.md +2 -2
- package/kb/site/reference/cookbook/adding-a-settings-card.md +2 -2
- 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 +6 -6
- 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 +19 -7
- package/kb/site/reference/persistence-catalog.md +87 -40
- 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 +3 -3
- package/kb/site/reference/subsystems/compaction.md +2 -2
- package/kb/site/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +43 -24
- package/kb/site/reference/subsystems/core.md +70 -12
- package/kb/site/reference/subsystems/credentials.md +43 -3
- package/kb/site/reference/subsystems/filesystem.md +12 -2
- package/kb/site/reference/subsystems/index.md +6 -1
- package/kb/site/reference/subsystems/jobs.md +1 -1
- package/kb/site/reference/subsystems/llm-streaming.md +132 -11
- package/kb/site/reference/subsystems/persistence.md +22 -3
- package/kb/site/reference/subsystems/plan.md +1 -1
- package/kb/site/reference/subsystems/session-projection.md +74 -33
- package/kb/site/reference/subsystems/session-query.md +9 -1
- package/kb/site/reference/subsystems/session-reference.md +28 -7
- package/kb/site/reference/subsystems/session-telemetry.md +2 -3
- package/kb/site/reference/subsystems/session.md +260 -41
- package/kb/site/reference/subsystems/settings.md +78 -1
- package/kb/site/reference/subsystems/skills.md +23 -0
- package/kb/site/reference/subsystems/slots.md +177 -0
- package/kb/site/reference/subsystems/spill.md +2 -2
- package/kb/site/reference/subsystems/storage.md +9 -1
- package/kb/site/reference/subsystems/subagent.md +90 -23
- package/kb/site/reference/subsystems/system-prompt.md +4 -4
- package/kb/site/reference/subsystems/token-meter.md +25 -10
- package/kb/site/reference/subsystems/tools.md +39 -39
- package/kb/site/reference/subsystems/typert.md +44 -37
- 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 +95 -2
- package/kb/site/reference/tool-catalog.md +76 -18
- package/kb/site/reference/tool-execution-pipeline.md +1 -1
- package/package.json +2 -2
- package/skills/dsh-plugin-dev-kb.md +8 -6
|
@@ -31,7 +31,19 @@ interface ContentBlockMap {
|
|
|
31
31
|
}
|
|
32
32
|
```
|
|
33
33
|
|
|
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:
|
|
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
|
+
|
|
36
|
+
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
|
+
Source: [`packages/llm/llm/src/content.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/content.ts)
|
|
39
|
+
|
|
40
|
+
```ts type-equiv
|
|
41
|
+
/** Execution-world path that model tools can use to read one normalized attachment. */
|
|
42
|
+
interface ImageAttachmentAccess {
|
|
43
|
+
/** Absolute path to immutable normalized bytes; callers must treat it as read-only. */
|
|
44
|
+
readonlyPath: string
|
|
45
|
+
}
|
|
46
|
+
```
|
|
35
47
|
|
|
36
48
|
Source: [`packages/llm/llm/src/message.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/message.ts)
|
|
37
49
|
|
|
@@ -196,7 +208,7 @@ type StreamChunk =
|
|
|
196
208
|
| { type: 'block-start'; index: number; blockType: ContentBlockType }
|
|
197
209
|
| { type: 'text-delta'; index: number; text: string }
|
|
198
210
|
| { type: 'reasoning-delta'; index: number; text: string }
|
|
199
|
-
| { type: 'tool-call-delta'; index: number; id:
|
|
211
|
+
| { type: 'tool-call-delta'; index: number; id: ToolCallId; name?: string; argumentsDelta: string }
|
|
200
212
|
| { type: 'block-end'; index: number; block: ContentBlock }
|
|
201
213
|
| { type: 'usage'; usage: TokenUsage }
|
|
202
214
|
| {
|
|
@@ -227,6 +239,44 @@ interface LlmFailure {
|
|
|
227
239
|
}
|
|
228
240
|
```
|
|
229
241
|
|
|
242
|
+
## Request-image pricing
|
|
243
|
+
|
|
244
|
+
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.
|
|
245
|
+
|
|
246
|
+
```ts type-equiv
|
|
247
|
+
/**
|
|
248
|
+
* Request price of one ordered image occurrence under one exact model route's
|
|
249
|
+
* request projection. Every occurrence resolves to the pair the wire actually
|
|
250
|
+
* carries: provider visual tokens for a retained image, plus the model-visible
|
|
251
|
+
* text sent with or instead of it (request-preview handle, offload placeholder,
|
|
252
|
+
* or text-only substitution). The caller prices `text` with its own text
|
|
253
|
+
* estimator so provider pricing never fixes a text tokenization.
|
|
254
|
+
*/
|
|
255
|
+
interface LlmImageRequestPrice {
|
|
256
|
+
/** Provider visual tokens for the retained request image; 0 when only text represents this occurrence. */
|
|
257
|
+
visualTokens: number
|
|
258
|
+
/** Model-visible text sent for this occurrence, to be priced by the caller's text estimator. */
|
|
259
|
+
text: string
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
```ts type-equiv
|
|
264
|
+
/**
|
|
265
|
+
* Provider-side request-image pricing for one exact model route. Implemented
|
|
266
|
+
* by adapters whose provider charges visual tokens; consumers (the token
|
|
267
|
+
* meter) resolve it synchronously per measurement, so implementations must not
|
|
268
|
+
* perform I/O.
|
|
269
|
+
*/
|
|
270
|
+
interface LlmImageRequestPricing {
|
|
271
|
+
/**
|
|
272
|
+
* Price every image occurrence of one request projection.
|
|
273
|
+
* @param images - durable image references in request order, one entry per occurrence.
|
|
274
|
+
* @returns one price per occurrence, aligned by index with `images`.
|
|
275
|
+
*/
|
|
276
|
+
priceImages(images: readonly ImageAttachmentRef[]): readonly LlmImageRequestPrice[]
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
230
280
|
## The adapter contract
|
|
231
281
|
|
|
232
282
|
Every adapter MUST obey these, and every consumer may rely on them:
|
|
@@ -269,7 +319,7 @@ interface AppIdentity {
|
|
|
269
319
|
|
|
270
320
|
## `TokenUsage`
|
|
271
321
|
|
|
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.
|
|
322
|
+
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
323
|
|
|
274
324
|
```ts type-equiv
|
|
275
325
|
/**
|
|
@@ -283,6 +333,14 @@ Per-call token accounting. Counts are **disjoint**: `inputTokens` is uncached in
|
|
|
283
333
|
interface TokenUsage {
|
|
284
334
|
inputTokens: number
|
|
285
335
|
outputTokens: number
|
|
336
|
+
/**
|
|
337
|
+
* Exact full-call total including aggregate prompt and output tokens.
|
|
338
|
+
*
|
|
339
|
+
* Adapters preserve a provider total or derive it from authoritative
|
|
340
|
+
* aggregate prompt/output counters; they omit it when unavailable or
|
|
341
|
+
* inconsistent.
|
|
342
|
+
*/
|
|
343
|
+
totalTokens?: number
|
|
286
344
|
cacheReadTokens?: number
|
|
287
345
|
cacheWriteTokens?: number
|
|
288
346
|
reasoningTokens?: number
|
|
@@ -356,7 +414,7 @@ One model call is a fully-assembled `GenerateOptions`. The adapter answers with
|
|
|
356
414
|
|
|
357
415
|
Source: [`packages/llm/llm/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm/src/types.ts)
|
|
358
416
|
|
|
359
|
-
Provider and model discovery uses small provider-neutral descriptors. A model catalog is advisory: routing still keys on a registered provider
|
|
417
|
+
Provider and model discovery uses small provider-neutral descriptors. A model catalog is advisory: routing still keys on a registered provider.
|
|
360
418
|
|
|
361
419
|
Registering an adapter returns a handle: the disposer, plus the atomic route replacement a plugin whose route set is user-configurable needs.
|
|
362
420
|
|
|
@@ -604,8 +662,6 @@ interface LlmModelDiscoveryRequest {
|
|
|
604
662
|
api?: string
|
|
605
663
|
/** Credential for this interrogation alone; the harness never stores it. */
|
|
606
664
|
apiKey?: string
|
|
607
|
-
/** Caller cancellation; implementations must settle promptly after it aborts. */
|
|
608
|
-
signal?: AbortSignal
|
|
609
665
|
}
|
|
610
666
|
```
|
|
611
667
|
|
|
@@ -665,6 +721,12 @@ interface LlmCallConfigAdapterDefaults {
|
|
|
665
721
|
}
|
|
666
722
|
```
|
|
667
723
|
|
|
724
|
+
## Official DeepSeek request extensions
|
|
725
|
+
|
|
726
|
+
`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.
|
|
727
|
+
|
|
728
|
+
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.
|
|
729
|
+
|
|
668
730
|
## Service and provider contracts
|
|
669
731
|
|
|
670
732
|
`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 +775,16 @@ declare abstract class LlmAdapter {
|
|
|
713
775
|
* @returns a resolved policy, or `undefined` to use the normal defaults.
|
|
714
776
|
*/
|
|
715
777
|
providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined;
|
|
778
|
+
/**
|
|
779
|
+
* Resolve provider-side request-image pricing for one exact model route.
|
|
780
|
+
* The default declares none, so consumers fall back to their own neutral
|
|
781
|
+
* estimate. Implementations must answer synchronously without I/O; the
|
|
782
|
+
* token meter resolves this per measurement.
|
|
783
|
+
* @param _provider - a route passed to `registerAdapter()` for this instance.
|
|
784
|
+
* @param _model - exact model id passed to {@link GenerateOptions.model}.
|
|
785
|
+
* @returns route-owned image pricing, or `undefined` when the route declares none.
|
|
786
|
+
*/
|
|
787
|
+
imageRequestPricing(_provider: string, _model: string): LlmImageRequestPricing | undefined;
|
|
716
788
|
/**
|
|
717
789
|
* List models this adapter can currently advertise for one owned provider.
|
|
718
790
|
* The result is advisory: an adapter may accept unlisted model ids, and
|
|
@@ -764,6 +836,33 @@ declare abstract class LlmAdapter {
|
|
|
764
836
|
|
|
765
837
|
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
838
|
|
|
839
|
+
<a id="ctxdeepseekllmapiextensions--deepseekllmapiextensionregistry"></a>
|
|
840
|
+
|
|
841
|
+
### `ctx.deepseekLlmApiExtensions` — `DeepSeekLlmApiExtensionRegistry`
|
|
842
|
+
|
|
843
|
+
Registry of independently owned top-level fields for official DeepSeek requests.
|
|
844
|
+
|
|
845
|
+
```ts cordis-catalog
|
|
846
|
+
/**
|
|
847
|
+
* Register the sole provider of one top-level request field. Registration is effect-scoped.
|
|
848
|
+
* @param field - declaration-merged field owned by the provider.
|
|
849
|
+
* @param provider - request-time field preparation and optional acceptance behavior.
|
|
850
|
+
* @returns disposer that releases the field.
|
|
851
|
+
*/
|
|
852
|
+
register<K extends keyof DeepSeekLlmApiExtensionMap>( field: K, provider: DeepSeekLlmApiExtensionProvider<DeepSeekLlmApiExtensionMap[K]>, ): () => Promise<void>
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Prepare every currently registered field from one immutable base request.
|
|
856
|
+
* Preparation failures reject before HTTP dispatch. Field values are cloned and frozen;
|
|
857
|
+
* providers retain no mutable alias to the outgoing request.
|
|
858
|
+
* @param request - exact serialized request facts before extension fields.
|
|
859
|
+
* @returns detached fields and their idempotent joint acceptance transaction.
|
|
860
|
+
*/
|
|
861
|
+
async prepare(request: DeepSeekLlmApiExtensionRequest): Promise<PreparedDeepSeekLlmApiExtensions>
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
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)
|
|
865
|
+
|
|
767
866
|
<a id="ctxllm--llmruntime"></a>
|
|
768
867
|
|
|
769
868
|
### `ctx.llm` — `LlmRuntime`
|
|
@@ -785,7 +884,7 @@ registerAdapter(providers: string[], adapter: LlmAdapter): AdapterRegistrationHa
|
|
|
785
884
|
* Describe provider routes with a registered adapter.
|
|
786
885
|
* @returns detached provider metadata in registration order.
|
|
787
886
|
*/
|
|
788
|
-
listProviders(): LlmProviderInfo[]
|
|
887
|
+
@Remote listProviders(): LlmProviderInfo[]
|
|
789
888
|
|
|
790
889
|
/**
|
|
791
890
|
* Declare provider routes an adapter plugin can activate through
|
|
@@ -801,7 +900,7 @@ registerConfigurableProviders(entries: readonly LlmConfigurableProvider[]): Dire
|
|
|
801
900
|
* List every declared configurable provider, registered or dormant.
|
|
802
901
|
* @returns detached directory entries in declaration order.
|
|
803
902
|
*/
|
|
804
|
-
listConfigurableProviders(): LlmConfigurableProvider[]
|
|
903
|
+
@Remote listConfigurableProviders(): LlmConfigurableProvider[]
|
|
805
904
|
|
|
806
905
|
/**
|
|
807
906
|
* Offer to interrogate provider endpoints on behalf of the settings
|
|
@@ -810,10 +909,10 @@ listConfigurableProviders(): LlmConfigurableProvider[]
|
|
|
810
909
|
* directory, and because a provider being *added* has no route to name yet.
|
|
811
910
|
* Disposed with the fiber.
|
|
812
911
|
* @param settingsNs - the namespace whose profiles this discovery serves.
|
|
813
|
-
* @param discover - interrogates one endpoint
|
|
912
|
+
* @param discover - interrogates one endpoint and must honor the supplied signal.
|
|
814
913
|
* @returns the disposer that withdraws the offer.
|
|
815
914
|
*/
|
|
816
|
-
registerModelDiscovery( settingsNs: string, discover: (request: LlmModelDiscoveryRequest) => Promise<readonly LlmDiscoveredModel[]>, ): () => void
|
|
915
|
+
registerModelDiscovery( settingsNs: string, discover: ( request: LlmModelDiscoveryRequest, signal?: AbortSignal, ) => Promise<readonly LlmDiscoveredModel[]>, ): () => void
|
|
817
916
|
|
|
818
917
|
/**
|
|
819
918
|
* Interrogate one provider endpoint for the models it advertises. The
|
|
@@ -822,9 +921,20 @@ registerModelDiscovery( settingsNs: string, discover: (request: LlmModelDiscover
|
|
|
822
921
|
* candidate metadata a surface may offer for adoption.
|
|
823
922
|
* @param settingsNs - namespace whose registered discovery serves this draft.
|
|
824
923
|
* @param request - the endpoint, protocol, and one-shot credential to use.
|
|
924
|
+
* @param signal - caller cancellation.
|
|
825
925
|
* @returns the advertised models, deduplicated in endpoint order.
|
|
826
926
|
*/
|
|
827
|
-
async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, ): Promise<LlmDiscoveredModel[]>
|
|
927
|
+
async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, signal?: AbortSignal, ): Promise<LlmDiscoveredModel[]>
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* Remote adapter for one draft provider interrogation.
|
|
931
|
+
* @param settingsNs - namespace whose registered discovery serves this draft.
|
|
932
|
+
* @param request - endpoint, protocol, and one-shot credential to use.
|
|
933
|
+
* @param signal - caller cancellation supplied by the Remote carrier.
|
|
934
|
+
* @returns advertised models in endpoint order.
|
|
935
|
+
* @throws TypertRemoteFailure with `model-discovery-failed` when discovery refuses or fails.
|
|
936
|
+
*/
|
|
937
|
+
@Remote('discoverModels') async remoteDiscoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, signal: AbortSignal, ): Promise<LlmDiscoveredModel[]>
|
|
828
938
|
|
|
829
939
|
/**
|
|
830
940
|
* Resolve the retry policy captured when one provider route was registered.
|
|
@@ -833,6 +943,17 @@ async discoverModels( settingsNs: string, request: LlmModelDiscoveryRequest, ):
|
|
|
833
943
|
*/
|
|
834
944
|
providerRetryPolicy(provider: string): ResolvedRetryPolicy
|
|
835
945
|
|
|
946
|
+
/**
|
|
947
|
+
* Resolve provider-side request-image pricing for one exact route, or
|
|
948
|
+
* `undefined` when the provider is unregistered or declares none. Unknown
|
|
949
|
+
* providers degrade to `undefined` rather than throwing because callers
|
|
950
|
+
* price durable history whose route may no longer be mounted.
|
|
951
|
+
* @param provider - provider route named by a request header.
|
|
952
|
+
* @param model - exact model id named by the same header.
|
|
953
|
+
* @returns the owning adapter's image pricing for the route, when declared.
|
|
954
|
+
*/
|
|
955
|
+
imageRequestPricing(provider: string, model: string): LlmImageRequestPricing | undefined
|
|
956
|
+
|
|
836
957
|
/**
|
|
837
958
|
* Discover models advertised by one registered provider. Catalog membership
|
|
838
959
|
* is advisory and never changes routing or request validation.
|
|
@@ -66,7 +66,7 @@ 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
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; `effectivePermissionPreset(events)` folds the last one, and replay needs no catch-up state. 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
|
|
|
@@ -94,7 +94,7 @@ interface SessionHeader {
|
|
|
94
94
|
|
|
95
95
|
## Format refusal — logs a build cannot faithfully read
|
|
96
96
|
|
|
97
|
-
A backend refuses a log it cannot faithfully interpret with `SessionFormatUnsupportedError`, distinct from `SessionPersistenceCorruptionError` because nothing is damaged. A header `version` ahead of `SESSION_FORMAT_VERSION` names the direction ("written by a newer harness — upgrade the harness to open it"); one behind it states that this build ships no upgrade path. After legacy-shape normalization, an event type outside this build's generated
|
|
97
|
+
A backend refuses a log it cannot faithfully interpret with `SessionFormatUnsupportedError`, distinct from `SessionPersistenceCorruptionError` because nothing is damaged. A header `version` ahead of `SESSION_FORMAT_VERSION` names the direction ("written by a newer harness — upgrade the harness to open it"); one behind it states that this build ships no upgrade path. After legacy-shape normalization, an event type outside this build's generated set (`KNOWN_SESSION_EVENT_TYPES`, emitted by `gen-persistence-catalog`) also refuses reconstruction because silently skipping it could change how the rest of the log must be read. The message appends the raw log path when the backend keeps one artifact per session, so the refused text stays reachable. The JSONL backend refuses a foreign version straight from the raw header line, before validating this format version's header fields or decoding any event row — a structurally different future format still reports the upgrade direction, never "corrupt"; SQLite gates whole-file structure through its own `SCHEMA_VERSION` pragma first. Design rationale and the deferred upgrader chain live in the [fail-closed event-vocabulary note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/simplification/2026-08-25-fail-closed-session-event-vocabulary.md).
|
|
98
98
|
|
|
99
99
|
## `CreateSessionOptions` — seeding and metadata
|
|
100
100
|
|
|
@@ -236,7 +236,7 @@ interface SessionPersistenceSnapshot {
|
|
|
236
236
|
All implement the same abstract `SessionPersistence` (locate/create/append/prepare/load/inspect/readFrom/list/listSnapshots over `SessionEvent`, with optional cancellation on observation methods) and pass the shared `runPersistenceContract` suite:
|
|
237
237
|
|
|
238
238
|
- **[dsh-session-persistence-jsonl](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-persistence-jsonl)** — an append-only logical JSONL log per session, stored as checksummed concatenated Zstandard frames by default or raw lines by configuration, with crash-safe atomic writes, interrupted-turn recovery, and a read/replay path.
|
|
239
|
-
- **[dsh-session-persistence-sqlite](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-persistence-sqlite)** — an opt-in `node:sqlite` backend using schema
|
|
239
|
+
- **[dsh-session-persistence-sqlite](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-persistence-sqlite)** — an opt-in `node:sqlite` backend using schema 19 to store exact same-block delta runs in bounded physical `text-chunks`, `reasoning-chunks`, and `tool-call-chunks` rows. It reconstructs the complete logical event stream before returning it, packs only newly durable batches, and rejects older schemas rather than migrating them.
|
|
240
240
|
|
|
241
241
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
242
242
|
|
|
@@ -288,6 +288,14 @@ readRaw(_id: SessionId, signal?: AbortSignal): Promise<SessionRawArtifact | unde
|
|
|
288
288
|
*/
|
|
289
289
|
abstract create(meta: SessionHeader): Promise<void>
|
|
290
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Ensure a live session has a durable header even when it has no events.
|
|
293
|
+
* Ordinary sessions remain lazily materialized; lifecycle frontends call
|
|
294
|
+
* this only when an empty session itself is a durable resumable resource.
|
|
295
|
+
* @param _session - exact live session whose registered header is materialized.
|
|
296
|
+
*/
|
|
297
|
+
ensureMaterialized(_session: Session): Promise<void>
|
|
298
|
+
|
|
291
299
|
/**
|
|
292
300
|
* Durably persist a batch of events. Honors the append-only and contiguous-
|
|
293
301
|
* seq contracts: the first event's `seq` MUST equal the stored next-seq
|
|
@@ -342,6 +350,17 @@ abstract load(id: SessionId): Promise<SessionInspection>
|
|
|
342
350
|
*/
|
|
343
351
|
abstract inspect(id: SessionId, signal?: AbortSignal): Promise<SessionInspection>
|
|
344
352
|
|
|
353
|
+
/**
|
|
354
|
+
* Borrow one exact inspection while retaining any reusable prepared source.
|
|
355
|
+
* A cold observation must pin the exact prepared Session that a later
|
|
356
|
+
* {@link prepare} reserves. Implementations must not degrade this operation
|
|
357
|
+
* to a detached {@link inspect} result.
|
|
358
|
+
* @param id - persisted session to observe.
|
|
359
|
+
* @param signal - optional cancellation for preparation work.
|
|
360
|
+
* @returns a disposable immutable observation.
|
|
361
|
+
*/
|
|
362
|
+
abstract borrowSession(id: SessionId, signal?: AbortSignal): Promise<BorrowedSessionSource>
|
|
363
|
+
|
|
345
364
|
/**
|
|
346
365
|
* Read the stored events from `fromSeq` onward — the read-from-seq
|
|
347
366
|
* primitive for read models that resume from a watermark (e.g. a persisted
|
|
@@ -382,7 +401,7 @@ abstract list(signal?: AbortSignal): Promise<SessionHeader[]>
|
|
|
382
401
|
abstract listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot[]>
|
|
383
402
|
```
|
|
384
403
|
|
|
385
|
-
Types: [SessionEvent](./session.md) · [SessionId](./core.md)
|
|
404
|
+
Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionId](./core.md)
|
|
386
405
|
|
|
387
406
|
Source: [`packages/session/session-persistence/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-persistence/src/index.ts)
|
|
388
407
|
<!-- END GENERATED cordis-surface -->
|
|
@@ -29,7 +29,7 @@ interface PlanModeConfig {
|
|
|
29
29
|
}
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
A missing, blank, or non-string `section` and any unknown key fail at plugin load rather than being ignored. While plan mode is active, the exact `section` text renders as the `plan:policy` [system-prompt section](./system-prompt.md) at order
|
|
32
|
+
A missing, blank, or non-string `section` and any unknown key fail at plugin load rather than being ignored. While plan mode is active, the exact `section` text renders as the `plan:policy` [system-prompt section](./system-prompt.md) at first-party order 500; inactive plan mode contributes no text.
|
|
33
33
|
|
|
34
34
|
## The exit tool and the `/plan` command
|
|
35
35
|
|
|
@@ -5,7 +5,7 @@ outline: [2,3]
|
|
|
5
5
|
|
|
6
6
|
# Session Projections
|
|
7
7
|
|
|
8
|
-
The session-projection seam — a [capability seam](../capability-seams.md) through which domain host plugins serve whole current values of log-derived per-session state to client carriers: the Service Definition and registry ([dsh-session-projection](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-projection), `ctx.sessionProjections`), domain contributors (each registering one pure unit), and carriers ([dsh-
|
|
8
|
+
The session-projection seam — a [capability seam](../capability-seams.md) through which domain host plugins serve whole current values of log-derived per-session state to client carriers: the Service Definition and registry ([dsh-session-projection](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-projection), `ctx.sessionProjections`), domain contributors (each registering one pure unit), and carriers ([dsh-session-controller](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/api/session-controller)'s history tail page and `session/projection` push frame). It is one optional capability, not part of the agent-loop spine. The framework drives, the domain computes: the registry subscribes to `session/event` once and folds every committed event through every unit; domains hold no subscriptions and clients never fold domain events — they receive finished values. Design authority: the [session-projection RFC](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/proposed/architecture/2026-07-27-session-projection-and-command-log.md); drive/cache/feed contracts: the [package README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/README.md).
|
|
9
9
|
|
|
10
10
|
Source: [`packages/session/session-projection/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/src/index.ts)
|
|
11
11
|
|
|
@@ -31,10 +31,11 @@ interface ProjectionDefinition<
|
|
|
31
31
|
/** Validates persisted state before it seeds a fold. */
|
|
32
32
|
stateSchema: ZodType<S>
|
|
33
33
|
/**
|
|
34
|
-
* State for the empty log.
|
|
34
|
+
* State for the empty log and its immutable Session metadata.
|
|
35
|
+
* @param header - immutable metadata for the Session being projected.
|
|
35
36
|
* @returns the initial state.
|
|
36
37
|
*/
|
|
37
|
-
init(): NoInfer<S>
|
|
38
|
+
init(header: SessionHeader): NoInfer<S>
|
|
38
39
|
/**
|
|
39
40
|
* Pure transition: previous state + one committed event → next state. A
|
|
40
41
|
* unit uninterested in an event MUST return the same state reference — an
|
|
@@ -73,7 +74,7 @@ The whole-value event rule is load-bearing: a state-carrying log event carries t
|
|
|
73
74
|
/**
|
|
74
75
|
* One consistent read cut over every registered client-visible unit for one session.
|
|
75
76
|
* `asOfSeq` is the shared watermark — the seq of the last event every value
|
|
76
|
-
* reflects (`-1` for an empty log
|
|
77
|
+
* reflects (`-1` for an empty log).
|
|
77
78
|
*/
|
|
78
79
|
interface ProjectionSnapshot {
|
|
79
80
|
/** Seq of the last event the values reflect; -1 for an empty log. */
|
|
@@ -101,7 +102,7 @@ type ProjectionChangeListener = (
|
|
|
101
102
|
|
|
102
103
|
## The registry: `ctx.sessionProjections`
|
|
103
104
|
|
|
104
|
-
`SessionProjectionRegistry` ([signatures](#ctxsessionprojections--sessionprojectionregistry)) owns the drive: one `session/event` subscription, eager `apply` over every registered unit, and per-session per-unit watermark cells. Cells build lazily — a unit registered after events flowed, or a session older than the registry, folds `init` over the in-memory log on first touch (event or read). Registration is an effect whose disposer rides the calling fiber: an unloaded domain plugin's key (with its cached cells) disappears from subsequent drives and snapshots, and clients read that as capability absence; duplicate
|
|
105
|
+
`SessionProjectionRegistry` ([signatures](#ctxsessionprojections--sessionprojectionregistry)) owns the drive: one `session/event` subscription, eager `apply` over every registered unit, and per-session per-unit watermark cells. Cells build lazily — a unit registered after events flowed, or a session older than the registry, folds `init` over the in-memory log on first touch (event or read). Registration is an effect whose disposer rides the calling fiber: an unloaded domain plugin's key (with its cached cells) disappears from subsequent drives and snapshots, and clients read that as capability absence; a duplicate key with a different `stateVersion` throws, while same-version registrants share one unit and are counted. Domain plugins register under `ctx.inject(['sessionProjections'], …)` so headless assemblies without the registry stay unaffected.
|
|
105
106
|
|
|
106
107
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
107
108
|
|
|
@@ -115,49 +116,63 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
|
|
115
116
|
|
|
116
117
|
### `ctx.sessionProjectionCache` — `SessionProjectionCache`
|
|
117
118
|
|
|
118
|
-
The persisted projection cache service. Opens the `session_projcache` domain at init, checkpoints live sessions on a throttled write-behind (count/interval triggers from Config) plus
|
|
119
|
+
The persisted projection cache service. Opens the `session_projcache` domain at init, checkpoints live sessions on a throttled write-behind (count/interval triggers from Config) plus three mandatory points — session creation, `turn/end`, and session disposal (the live-to-cold moment) — and serves the cached rows for a session header. Every durable write is fail-soft: failures log a warning and the cache self-heals on the next write.
|
|
119
120
|
|
|
120
121
|
```ts cordis-catalog
|
|
121
122
|
/**
|
|
122
123
|
* The zero-I/O listing read: whole values viewed straight from the stored
|
|
123
|
-
* rows (version-matching keys only), each cut carried with its watermark
|
|
124
|
-
*
|
|
125
|
-
*
|
|
124
|
+
* rows (version-matching keys only), each cut carried with its watermark so
|
|
125
|
+
* a client value store can seed under its higher-seq-wins rule — as stale
|
|
126
|
+
* as the last durable checkpoint but never wrong, and never from an
|
|
126
127
|
* unrelated log (the caller's header is the identity witness). Fresher
|
|
127
|
-
* paths (the history tail baseline
|
|
128
|
-
*
|
|
128
|
+
* paths (the history tail baseline) supersede these values whenever a
|
|
129
|
+
* session is actually opened.
|
|
129
130
|
* @param meta - the listed session's header (identity witness; no log read).
|
|
131
|
+
* @param keys - optional projection keys required by the caller's audience.
|
|
130
132
|
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
|
131
133
|
* `undefined` when no usable row exists for this lifecycle.
|
|
132
134
|
*/
|
|
133
|
-
cachedSnapshot(meta: SessionHeader): ProjectionSnapshot | undefined
|
|
135
|
+
cachedSnapshot( meta: SessionHeader, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined
|
|
134
136
|
|
|
135
137
|
/**
|
|
136
|
-
*
|
|
138
|
+
* Hydrate projection cells for an already-prepared Session without another
|
|
139
|
+
* persistence read. The cache seeds matching rows; the supplied exact log
|
|
140
|
+
* advances every unit to the observation cut. No checkpoint is written
|
|
141
|
+
* because the logical observation may contain recovery events not yet durable.
|
|
142
|
+
* @param session - exact unpublished Session retained by persistence.
|
|
143
|
+
* @param meta - observed lifecycle header.
|
|
144
|
+
* @param events - exact logical event prefix represented by the observation.
|
|
145
|
+
* @returns all projection values at the event cut.
|
|
146
|
+
*/
|
|
147
|
+
hydratePrepared( session: Session, meta: SessionHeader, events: readonly SessionEvent[], ): ProjectionSnapshot
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Durably checkpoint one live session NOW (all mandatory points call
|
|
137
151
|
* this; tests and carriers may too). The registry cut is snapshotted at
|
|
138
|
-
* this boundary (states are live references), then the
|
|
139
|
-
* replaced. NOT fail-soft — callers on the
|
|
152
|
+
* this boundary (states are live references), then the session's record is
|
|
153
|
+
* replaced on the domain's write chain. NOT fail-soft — callers on the
|
|
154
|
+
* fail-soft paths contain it.
|
|
140
155
|
* @param session - the live session to checkpoint.
|
|
141
156
|
* @returns resolution after durability and event emission.
|
|
142
157
|
*/
|
|
143
158
|
async write(session: Session): Promise<void>
|
|
144
159
|
|
|
145
160
|
/**
|
|
146
|
-
* Cold-read one
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* @param
|
|
154
|
-
* @param
|
|
155
|
-
* @returns the
|
|
161
|
+
* Cold-read one session's projections from its complete log. Each unit is
|
|
162
|
+
* seeded from the identity-checked cached rows — the registry skips `apply`
|
|
163
|
+
* for the already-folded prefix (events at or below the row's `seq`) — and
|
|
164
|
+
* the refreshed checkpoint is written back (fail-soft, fire-and-forget), so
|
|
165
|
+
* the first cold read creates the cache row and later ones seed from it.
|
|
166
|
+
* The caller supplies the complete log in seq order: this service never
|
|
167
|
+
* consults the persistence layer.
|
|
168
|
+
* @param meta - the stored session header (identity witness).
|
|
169
|
+
* @param events - the session's complete log, in seq order.
|
|
170
|
+
* @returns the projection cut at the log end.
|
|
156
171
|
*/
|
|
157
|
-
|
|
172
|
+
coldSnapshot(meta: SessionHeader, events: readonly SessionEvent[]): ProjectionSnapshot
|
|
158
173
|
```
|
|
159
174
|
|
|
160
|
-
Types: [Session](./session.md) · [
|
|
175
|
+
Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md)
|
|
161
176
|
|
|
162
177
|
Source: [`packages/session/session-projection-cache/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection-cache/src/index.ts)
|
|
163
178
|
|
|
@@ -195,7 +210,8 @@ register< K extends Exclude<keyof SessionProjectionStateMap, keyof SessionProjec
|
|
|
195
210
|
onChanged(listener: ProjectionChangeListener): () => void
|
|
196
211
|
|
|
197
212
|
/**
|
|
198
|
-
* Read one unit's current host state
|
|
213
|
+
* Read one unit's current host state after materializing every registered
|
|
214
|
+
* unit at the Session cursor. Unrelated wire views are not produced.
|
|
199
215
|
* The returned value is live; callers must not mutate it.
|
|
200
216
|
* @param session - the session whose state is read.
|
|
201
217
|
* @param key - the registered unit key.
|
|
@@ -209,9 +225,20 @@ stateOf<K extends keyof SessionProjectionStateMap>( session: Session, key: K, ):
|
|
|
209
225
|
* Fully synchronous — every value and `asOfSeq` reflect the same log
|
|
210
226
|
* position. Each value passes its unit's `viewSchema` before leaving.
|
|
211
227
|
* @param session - the session whose projection values are read.
|
|
212
|
-
* @
|
|
228
|
+
* @param keys - optional client-visible outputs; state materialization remains complete.
|
|
229
|
+
* @returns the snapshot; `values` is empty when no selected client-visible unit is registered.
|
|
213
230
|
*/
|
|
214
|
-
snapshot(session: Session): ProjectionSnapshot
|
|
231
|
+
snapshot( session: Session, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Read only already-materialized client-visible cells without folding history.
|
|
235
|
+
* Values may trail the live Session and are therefore hints, not a complete
|
|
236
|
+
* baseline. Missing cells are omitted.
|
|
237
|
+
* @param session - attached Session whose cached cells are inspected.
|
|
238
|
+
* @param keys - optional wire keys to view.
|
|
239
|
+
* @returns the lowest common cached cut, or `undefined` when no wire cell exists.
|
|
240
|
+
*/
|
|
241
|
+
cachedSnapshot( session: Session, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined
|
|
215
242
|
|
|
216
243
|
/**
|
|
217
244
|
* State-level checkpoint of every persisted unit for one session, read
|
|
@@ -255,9 +282,10 @@ restoreFloor(checkpoint: ProjectionCheckpoint): number | undefined
|
|
|
255
282
|
* fuller read path refolds it). The zero-I/O rung of the read ladder —
|
|
256
283
|
* values are as stale as their rows, never wrong.
|
|
257
284
|
* @param checkpoint - persisted rows for one session (possibly stale or empty).
|
|
285
|
+
* @param keys - optional wire keys to view.
|
|
258
286
|
* @returns whole values per key with a usable row; empty when none.
|
|
259
287
|
*/
|
|
260
|
-
viewCheckpoint(checkpoint: ProjectionCheckpoint): Partial<SessionProjectionMap>
|
|
288
|
+
viewCheckpoint( checkpoint: ProjectionCheckpoint, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): Partial<SessionProjectionMap>
|
|
261
289
|
|
|
262
290
|
/**
|
|
263
291
|
* Cold read: fold every persisted unit over a stored log suffix, seeding
|
|
@@ -277,14 +305,27 @@ viewCheckpoint(checkpoint: ProjectionCheckpoint): Partial<SessionProjectionMap>
|
|
|
277
305
|
* @param checkpoint - persisted rows for one session (possibly stale or empty).
|
|
278
306
|
* @param events - the stored events with `seq >= baseSeq`, in seq order.
|
|
279
307
|
* @param baseSeq - the seq `events` starts at (its first event's seq when non-empty).
|
|
308
|
+
* @param header - immutable metadata for the Session being restored.
|
|
280
309
|
* @returns the snapshot cut at the supplied log end (`asOfSeq` is the last
|
|
281
310
|
* supplied event's seq, `baseSeq - 1` for an empty tail) plus the
|
|
282
311
|
* refreshed checkpoint rows at that cut, ready for a durable write-back.
|
|
283
312
|
*/
|
|
284
|
-
restore( checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: number, ): { snapshot: ProjectionSnapshot; checkpoint: ProjectionCheckpoint }
|
|
313
|
+
restore( checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: number, header: SessionHeader, ): { snapshot: ProjectionSnapshot; checkpoint: ProjectionCheckpoint }
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Restore an exact cut and install its states on the supplied prepared Session.
|
|
317
|
+
* A later publication reuses these cells; ordinary live reads and event drive
|
|
318
|
+
* advance any constructor-owned suffix exactly once.
|
|
319
|
+
* @param session - exact prepared Session that owns the restored log prefix.
|
|
320
|
+
* @param checkpoint - persisted rows for this Session lifecycle.
|
|
321
|
+
* @param events - exact events at the observation cut.
|
|
322
|
+
* @param baseSeq - first supplied event sequence.
|
|
323
|
+
* @returns all projection values at the supplied cut.
|
|
324
|
+
*/
|
|
325
|
+
hydrate( session: Session, checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: number, ): ProjectionSnapshot
|
|
285
326
|
```
|
|
286
327
|
|
|
287
|
-
Types: [Session](./session.md) · [SessionEvent](./session.md)
|
|
328
|
+
Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md)
|
|
288
329
|
|
|
289
330
|
Source: [`packages/session/session-projection/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/src/index.ts)
|
|
290
331
|
<!-- END GENERATED cordis-surface -->
|
|
@@ -141,7 +141,7 @@ interface SessionEventSearchDocument extends SessionEventRecord {
|
|
|
141
141
|
}
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
`ctx.sessionQuery.filterSessions(filters)` applies `SessionResultFilter` to the complete logical corpus; `ctx.sessionQuery.filterEvents(sessionId, filters)` returns matching documents in ascending seq order. Messages,
|
|
144
|
+
`ctx.sessionQuery.filterSessions(filters)` applies `SessionResultFilter` to the complete logical corpus; `ctx.sessionQuery.filterEvents(sessionId, filters)` returns matching documents in ascending seq order. Messages, tool calls/results, todos, and failure/status detail contribute semantic text; reasoning blocks, blocked prompts, structural events, and stream chunks do not.
|
|
145
145
|
|
|
146
146
|
## Full-text search pages
|
|
147
147
|
|
|
@@ -376,6 +376,14 @@ Unified live-preferred session query service.
|
|
|
376
376
|
Exact reads, filters, and traces are backend-independent concrete behavior. A backend implements full-text observation, reconciliation, ranking, cursor generations, and query execution on the same `ctx.sessionQuery` service.
|
|
377
377
|
|
|
378
378
|
```ts cordis-catalog
|
|
379
|
+
/**
|
|
380
|
+
* Observe one exact live or prepared Session without a persistence listing preflight.
|
|
381
|
+
* @param sessionId - logical Session identity.
|
|
382
|
+
* @param options - cancellation and projection selection for this read.
|
|
383
|
+
* @returns a caller-owned observation lease.
|
|
384
|
+
*/
|
|
385
|
+
observeSession( sessionId: SessionId, options: SessionObservationOptions = {}, ): Promise<SessionObservation>
|
|
386
|
+
|
|
379
387
|
/**
|
|
380
388
|
* Search the live-preferred logical corpus and group by session.
|
|
381
389
|
* @param request - query text, metadata filters, page size, and cursor.
|