dsh-plugin-dev-kb 1.0.9 → 1.3.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 +26 -0
- package/README.en.md +14 -8
- package/README.md +14 -8
- package/docs/banner.svg +25 -0
- package/kb/INDEX.md +8 -2
- package/kb/README.md +4 -4
- package/kb/extra/AGENTS.md +3 -3
- 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-session-format-version.md +109 -0
- package/kb/extra/cookbook/adding-a-session-format-version.zh.md +109 -0
- package/kb/extra/cookbook/adding-a-vendored-package.md +1 -1
- package/kb/extra/cookbook/adding-a-vendored-package.zh.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +1 -1
- package/kb/extra/deepseek-llm-api-wire-extensions.md +19 -15
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +19 -15
- package/kb/extra/development.md +13 -3
- package/kb/extra/development.zh.md +13 -3
- package/kb/extra/event-producer-consumer.md +49 -46
- package/kb/extra/event-producer-consumer.zh.md +52 -49
- package/kb/extra/i18n/README.md +2 -1
- package/kb/extra/i18n/README.zh.md +3 -2
- package/kb/extra/i18n/style-samples.md +2 -2
- package/kb/extra/i18n/translation-prompt.md +1 -1
- package/kb/extra/module-graph.md +493 -1002
- package/kb/extra/module-graph.zh.md +495 -1004
- package/kb/extra/rescope.md +1 -1
- package/kb/extra/rescope.zh.md +1 -1
- package/kb/extra/session-format-status.md +47 -0
- package/kb/extra/session-format-status.zh.md +47 -0
- package/kb/extra/subsystems/agent-team.md +3 -2
- package/kb/extra/subsystems/agent-team.zh.md +3 -2
- package/kb/extra/subsystems/attachment.md +157 -4
- package/kb/extra/subsystems/attachment.zh.md +157 -4
- package/kb/extra/subsystems/feedback.md +164 -30
- package/kb/extra/subsystems/feedback.zh.md +164 -30
- package/kb/extra/testing.md +9 -4
- package/kb/extra/testing.zh.md +9 -4
- package/kb/extra/web-styling.md +5 -0
- package/kb/extra/web-styling.zh.md +5 -0
- package/kb/meta/search-index.json +223 -151
- package/kb/meta/site-pages.txt +187 -181
- package/kb/meta/source.json +5 -5
- package/kb/meta/topics.md +5 -5
- package/kb/site/develop/basic/publish.md +1 -1
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/develop/basic/publish.md +1 -1
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/en/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/guide/network-proxy.md +87 -0
- package/kb/site/en/guide/providers.md +70 -17
- package/kb/site/en/guide/python-sdk.md +19 -3
- package/kb/site/en/guide/schedule.md +2 -0
- package/kb/site/en/reference/agent-lifecycle.md +17 -8
- package/kb/site/en/reference/api-gateway.md +2 -2
- package/kb/site/en/reference/capability-seams.md +24 -10
- package/kb/site/en/reference/config-catalog.md +322 -264
- package/kb/site/en/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/en/reference/cookbook/adding-a-tool.md +1 -1
- package/kb/site/en/reference/cookbook/extension-cookbook.md +16 -13
- package/kb/site/en/reference/index.md +26 -9
- package/kb/site/en/reference/persistence-catalog.md +189 -95
- package/kb/site/en/reference/subsystems/approval.md +1 -1
- package/kb/site/en/reference/subsystems/client-modules.md +9 -0
- package/kb/site/en/reference/subsystems/client-resources.md +94 -0
- package/kb/site/en/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/en/reference/subsystems/commands.md +25 -16
- package/kb/site/en/reference/subsystems/compaction.md +10 -10
- package/kb/site/en/reference/subsystems/conversation.md +11 -4
- package/kb/site/en/reference/subsystems/core.md +173 -29
- package/kb/site/en/reference/subsystems/credentials.md +5 -4
- package/kb/site/en/reference/subsystems/filesystem.md +15 -0
- package/kb/site/en/reference/subsystems/goal.md +38 -2
- package/kb/site/en/reference/subsystems/index.md +3 -1
- package/kb/site/en/reference/subsystems/invariants.md +1 -1
- package/kb/site/en/reference/subsystems/llm-streaming.md +43 -12
- package/kb/site/en/reference/subsystems/lsp.md +1 -1
- package/kb/site/en/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/en/reference/subsystems/persistence.md +211 -199
- package/kb/site/en/reference/subsystems/plan.md +3 -3
- package/kb/site/en/reference/subsystems/sandbox.md +2 -0
- package/kb/site/en/reference/subsystems/schedule.md +9 -3
- package/kb/site/en/reference/subsystems/scope.md +1 -1
- package/kb/site/en/reference/subsystems/session-projection.md +50 -24
- package/kb/site/en/reference/subsystems/session-query.md +19 -13
- package/kb/site/en/reference/subsystems/session-reference.md +29 -1
- package/kb/site/en/reference/subsystems/session-telemetry.md +27 -10
- package/kb/site/en/reference/subsystems/session-title.md +6 -6
- package/kb/site/en/reference/subsystems/session.md +208 -103
- package/kb/site/en/reference/subsystems/settings.md +30 -12
- package/kb/site/en/reference/subsystems/shell.md +9 -6
- package/kb/site/en/reference/subsystems/sidebar-right.md +151 -0
- package/kb/site/en/reference/subsystems/skills.md +1 -1
- package/kb/site/en/reference/subsystems/slots.md +41 -32
- package/kb/site/en/reference/subsystems/spill.md +13 -6
- package/kb/site/en/reference/subsystems/storage.md +28 -5
- package/kb/site/en/reference/subsystems/subagent.md +58 -105
- package/kb/site/en/reference/subsystems/subprocess.md +25 -26
- package/kb/site/en/reference/subsystems/system-prompt.md +18 -3
- package/kb/site/en/reference/subsystems/token-meter.md +4 -3
- package/kb/site/en/reference/subsystems/tools.md +5 -5
- package/kb/site/en/reference/subsystems/typert.md +18 -18
- package/kb/site/en/reference/subsystems/web-client.md +1 -1
- package/kb/site/en/reference/subsystems/workspace.md +88 -9
- package/kb/site/en/reference/tool-catalog.md +56 -66
- package/kb/site/en/reference/tool-execution-pipeline.md +2 -2
- package/kb/site/guide/network-proxy.md +87 -0
- package/kb/site/guide/providers.md +70 -17
- package/kb/site/guide/python-sdk.md +19 -3
- package/kb/site/guide/schedule.md +2 -0
- package/kb/site/reference/agent-lifecycle.md +17 -8
- package/kb/site/reference/api-gateway.md +2 -2
- package/kb/site/reference/capability-seams.md +24 -10
- package/kb/site/reference/config-catalog.md +321 -263
- package/kb/site/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/reference/cookbook/adding-a-tool.md +1 -1
- package/kb/site/reference/cookbook/extension-cookbook.md +16 -13
- package/kb/site/reference/index.md +26 -9
- package/kb/site/reference/persistence-catalog.md +190 -96
- package/kb/site/reference/subsystems/approval.md +1 -1
- package/kb/site/reference/subsystems/client-modules.md +9 -0
- package/kb/site/reference/subsystems/client-resources.md +94 -0
- package/kb/site/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/reference/subsystems/commands.md +25 -16
- package/kb/site/reference/subsystems/compaction.md +10 -10
- package/kb/site/reference/subsystems/conversation.md +11 -4
- package/kb/site/reference/subsystems/core.md +173 -29
- package/kb/site/reference/subsystems/credentials.md +5 -4
- package/kb/site/reference/subsystems/filesystem.md +15 -0
- package/kb/site/reference/subsystems/goal.md +38 -2
- package/kb/site/reference/subsystems/index.md +14 -12
- package/kb/site/reference/subsystems/invariants.md +1 -1
- package/kb/site/reference/subsystems/llm-streaming.md +43 -12
- package/kb/site/reference/subsystems/lsp.md +1 -1
- package/kb/site/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/reference/subsystems/persistence.md +210 -198
- package/kb/site/reference/subsystems/plan.md +3 -3
- package/kb/site/reference/subsystems/schedule.md +9 -3
- package/kb/site/reference/subsystems/scope.md +1 -1
- package/kb/site/reference/subsystems/session-projection.md +50 -24
- package/kb/site/reference/subsystems/session-query.md +19 -13
- package/kb/site/reference/subsystems/session-reference.md +29 -1
- package/kb/site/reference/subsystems/session-telemetry.md +27 -10
- package/kb/site/reference/subsystems/session-title.md +6 -6
- package/kb/site/reference/subsystems/session.md +208 -103
- package/kb/site/reference/subsystems/settings.md +30 -12
- package/kb/site/reference/subsystems/shell.md +9 -6
- package/kb/site/reference/subsystems/sidebar-right.md +151 -0
- package/kb/site/reference/subsystems/skills.md +1 -1
- package/kb/site/reference/subsystems/slots.md +41 -32
- package/kb/site/reference/subsystems/spill.md +13 -6
- package/kb/site/reference/subsystems/storage.md +28 -5
- package/kb/site/reference/subsystems/subagent.md +58 -105
- package/kb/site/reference/subsystems/subprocess.md +25 -26
- package/kb/site/reference/subsystems/system-prompt.md +18 -3
- package/kb/site/reference/subsystems/token-meter.md +4 -3
- package/kb/site/reference/subsystems/tools.md +5 -5
- package/kb/site/reference/subsystems/typert.md +18 -18
- package/kb/site/reference/subsystems/web-client.md +1 -1
- package/kb/site/reference/subsystems/workspace.md +88 -9
- package/kb/site/reference/tool-catalog.md +55 -65
- package/kb/site/reference/tool-execution-pipeline.md +2 -2
- package/lib/index.js +25 -44
- package/package.json +3 -2
- package/skills/dsh-plugin-dev-kb.md +4 -4
|
@@ -11,7 +11,7 @@ Source: [`packages/plan/plan-mode/src/index.ts`](https://github.com/deepseek-ai/
|
|
|
11
11
|
|
|
12
12
|
## Logged state and recovery
|
|
13
13
|
|
|
14
|
-
`plan/mode` (`{ active: boolean }`) is a log-only, whole-value-replace [session event](./session.md): durable and replayable, never in the model transcript. `
|
|
14
|
+
`plan/mode` (`{ active: boolean }`) is a log-only, whole-value-replace [session event](./session.md): durable and replayable, never in the model transcript. The optionally registered `plan` unit folds committed mode, command settlement, and the mode recorded at the latest request header. `ctx.planMode` reads that state through `stateOf()`; the first dependent access fails if the registry, `plan` key, or `turnBoundary` key is absent. Clients receive only `{ active, pending }`; resume, fork, and compaction recover both from the log. The complete event declaration is in the [persistence log event catalog](../persistence-catalog.md).
|
|
15
15
|
|
|
16
16
|
## Pending selections and the pre-step append
|
|
17
17
|
|
|
@@ -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
|
|
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 50; inactive plan mode contributes no text.
|
|
33
33
|
|
|
34
34
|
## The exit tool and the `/plan` command
|
|
35
35
|
|
|
@@ -53,7 +53,7 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
|
|
53
53
|
|
|
54
54
|
### `ctx.planMode` — `PlanModeController`
|
|
55
55
|
|
|
56
|
-
`ctx.planMode`: owns logged plan state, applies and narrates selected state at step start, the `plan:policy` section, the `/plan` command, and the stable exit tool.
|
|
56
|
+
`ctx.planMode`: owns logged plan state, applies and narrates selected state at step start, the `plan:policy` section, the `/plan` command, and the stable exit tool. Client carriers expose the projection's cropped `{ active, pending }` view.
|
|
57
57
|
|
|
58
58
|
```ts cordis-catalog
|
|
59
59
|
/**
|
|
@@ -96,6 +96,8 @@ interface SandboxPolicy extends SandboxExecutionPolicy {
|
|
|
96
96
|
}
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
<a id="wrapped-argv-and-classification-dialects"></a>
|
|
100
|
+
|
|
99
101
|
## Wrapped argv and classification dialects
|
|
100
102
|
|
|
101
103
|
`RunnerFailureRule` combines evidence that a runner failed before executing the command. A consumer requires a nonzero exit, the optional allowed-exit-code gate, and a case-insensitive fatal signature within one remaining stderr line. Case-insensitive exact full-line informational exclusions are removed first, so a benign runner notice cannot prove failure by itself. The matched line remains available as error detail; classification does not rewrite stderr.
|
|
@@ -5,7 +5,7 @@ outline: [2,3]
|
|
|
5
5
|
|
|
6
6
|
# Session-local Schedule
|
|
7
7
|
|
|
8
|
-
Schedule owns durable reminders that return to the original live Session as ordinary later conversation turns. The [durable Schedule Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-08-05-durable-web-schedule.md) owns
|
|
8
|
+
Schedule owns durable reminders that return to the original live Session as ordinary later conversation turns. The [durable Schedule Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-08-05-durable-web-schedule.md) owns persistence, lifecycle, and active-state presentation, and the [explicit time-zone boundary](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/simplification/2026-08-09-explicit-schedule-time-zone.md) owns browser-local interpretation. This page records the durable and model-facing shapes from [`packages/schedule/schedule/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/schedule/schedule/src/types.ts); the [package README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/schedule/schedule/README.md) owns composition, tool behavior, and the exact reminder framing.
|
|
9
9
|
|
|
10
10
|
## Durable records
|
|
11
11
|
|
|
@@ -152,7 +152,7 @@ type ScheduleDispatchChange = OneShotScheduleDispatchChange | EveryScheduleDispa
|
|
|
152
152
|
type ScheduleChange = ScheduleCreateChange | ScheduleDeleteChange | ScheduleDispatchChange
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
The strict decoder and fold reject unknown versions, extra fields, reused ids, mismatched one-shot or Every dispatch shapes, and delete or dispatch transitions against inactive records. A normal Session folds its complete event stream. A fork folds only events at or after `
|
|
155
|
+
The strict decoder and fold reject unknown versions, extra fields, reused ids, mismatched one-shot or Every dispatch shapes, and delete or dispatch transitions against inactive records. A normal Session folds its complete event stream. A fork folds only events at or after its exact `inheritedEventCount`, so it retains history without adopting the parent Session's active reminders. Projection initialization receives that cut beside the immutable header, uses the shared transition, and persists both the cut, active records, and used-id history so cached restore preserves strict replay. The `schedule/change` declaration and source location are also indexed in the [persistence catalog](../persistence-catalog.md#schedulechange--log-only).
|
|
156
156
|
|
|
157
157
|
## Active views and management
|
|
158
158
|
|
|
@@ -180,10 +180,16 @@ type ScheduleView = ScheduleRecord & {
|
|
|
180
180
|
|
|
181
181
|
The generated [tool catalog](../tool-catalog.md#deepseek-aidsh-schedule) owns the argument and result schemas for `schedule_create`, `schedule_list`, and `schedule_delete`. Management calls serialize with due work in one Agent-scoped queue. Every read or decision first waits for the shared Session persistence barrier; create and an actual delete wait again after appending. A barrier failure reports `persistence_uncertain` instead of guessing whether an eager write committed. The other stable error codes are `invalid_prompt`, `invalid_selector`, `invalid_rule`, `invalid_time_zone`, `not_future`, `time_out_of_range`, `frequency_too_high`, `corrupt_schedule_log`, and `internal_error`.
|
|
182
182
|
|
|
183
|
+
## Read-only Web catalog
|
|
184
|
+
|
|
185
|
+
When the optional Session projection registry is present, Schedule registers the client-visible `schedule` key whose value is the complete active `ScheduleRecord[]`. Live, cache, history, and detached reads use the same header-aware strict fold; malformed authoritative input fails the existing read path instead of publishing a partial value.
|
|
186
|
+
|
|
187
|
+
The shipped Web bundle keeps `ui-schedule` disabled by default, while the explicit Schedule overlay enables it together with the Host capability. [`dsh-client-ui-schedule`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-schedule/README.md) owns the header interaction, [`dsh-client-ui-workspace`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-workspace/README.md) owns list-row presentation, and the durable Schedule Agent Note owns their shared active-state boundary. The shared value represents current active state, never delivery history or a receipt; due reminders still appear through the ordinary Assistant output described below.
|
|
188
|
+
|
|
183
189
|
## Live delivery
|
|
184
190
|
|
|
185
191
|
The process-local owner derives its earliest timer from the durable fold and rereads the wall clock after every bounded wait. Cold Sessions do no work; reopening one reconstructs timers and makes past targets overdue. Due one-shots take priority and enter one later turn at a time. When no one-shot is due, all overdue Every records form the single batch described above.
|
|
186
192
|
|
|
187
193
|
Due work waits for the Agent to become fully idle and claims the maintenance phase before it refolds state, samples the decision, queues one `followup()`, and appends the corresponding dispatch changes. It never calls `steer()` and never interrupts a current turn.
|
|
188
194
|
|
|
189
|
-
The admitted one-shot or fixed-rate batch starts one normal later turn and appears only through the ordinary conversation transcript; Schedule has no independent durable Web receipt
|
|
195
|
+
The admitted one-shot or fixed-rate batch starts one normal later turn and appears only through the ordinary conversation transcript; Schedule has no independent durable Web receipt. The read-only active catalog above never represents delivery success. If framing or synchronous queue admission fails, no dispatch is recorded and the reminder stays active. The narrow crash interval after admission but before durable dispatch can repeat reminder content after recovery, so the boundary is best-effort at-least-once rather than exactly-once delivery.
|
|
@@ -5,7 +5,7 @@ outline: [2,3]
|
|
|
5
5
|
|
|
6
6
|
# Scoped Registration
|
|
7
7
|
|
|
8
|
-
The [scope package](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/scope) supplies the identity, carrier, and scoped-layer vocabulary that makes one registration context mean both per-agent visibility and shared lifetime ownership. It is a library primitive rather than a Cordis service; the [agent-scope runtime-design Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.md#scope-routing-one-opaque-key-selects-one-layer) owns the lifecycle rationale,
|
|
8
|
+
The [scope package](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/scope) supplies the identity, carrier, and scoped-layer vocabulary that makes one registration context mean both per-agent visibility and shared lifetime ownership. It is a library primitive rather than a Cordis service; the [agent-scope runtime-design Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.md#scope-routing-one-opaque-key-selects-one-layer) owns the lifecycle rationale, and the package [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/scope/README.md) owns the callable API and filtering semantics.
|
|
9
9
|
|
|
10
10
|
Sources: [`packages/core/scope/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/scope/src/index.ts) and [`packages/core/scope/src/store.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/scope/src/store.ts).
|
|
11
11
|
|
|
@@ -33,9 +33,10 @@ interface ProjectionDefinition<
|
|
|
33
33
|
/**
|
|
34
34
|
* State for the empty log and its immutable Session metadata.
|
|
35
35
|
* @param header - immutable metadata for the Session being projected.
|
|
36
|
+
* @param inheritedEventCount - exact fork-inherited prefix length.
|
|
36
37
|
* @returns the initial state.
|
|
37
38
|
*/
|
|
38
|
-
init(header: SessionHeader): NoInfer<S>
|
|
39
|
+
init(header: SessionHeader, inheritedEventCount: SessionLogOffset): NoInfer<S>
|
|
39
40
|
/**
|
|
40
41
|
* Pure transition: previous state + one committed event → next state. A
|
|
41
42
|
* unit uninterested in an event MUST return the same state reference — an
|
|
@@ -50,7 +51,10 @@ interface ProjectionDefinition<
|
|
|
50
51
|
/** Validates the wire payload before it leaves the host. */
|
|
51
52
|
viewSchema: ZodType<SessionProjectionMap[K]>
|
|
52
53
|
/**
|
|
53
|
-
* State → wire payload (the read-side projection).
|
|
54
|
+
* State → wire payload (the read-side projection). The live drive keeps
|
|
55
|
+
* the two latest raw results and compares them with `Object.is`; an
|
|
56
|
+
* object-valued view must reuse its reference to suppress publication
|
|
57
|
+
* across internal-only state changes.
|
|
54
58
|
* @param state - the current state.
|
|
55
59
|
* @returns the whole current value for this unit's key.
|
|
56
60
|
*/
|
|
@@ -78,7 +82,7 @@ The whole-value event rule is load-bearing: a state-carrying log event carries t
|
|
|
78
82
|
*/
|
|
79
83
|
interface ProjectionSnapshot {
|
|
80
84
|
/** Seq of the last event the values reflect; -1 for an empty log. */
|
|
81
|
-
asOfSeq:
|
|
85
|
+
asOfSeq: SessionSeqCursor
|
|
82
86
|
/** Whole current client value per registered key. */
|
|
83
87
|
values: Partial<SessionProjectionMap>
|
|
84
88
|
}
|
|
@@ -86,19 +90,19 @@ interface ProjectionSnapshot {
|
|
|
86
90
|
|
|
87
91
|
```ts type-equiv
|
|
88
92
|
/**
|
|
89
|
-
* Change-feed listener: one unit's
|
|
90
|
-
* the schema-validated
|
|
91
|
-
* emission (the seq of the event that caused the change).
|
|
93
|
+
* Change-feed listener: one unit's raw `view` result changed by `Object.is`
|
|
94
|
+
* for one session. `value` is the schema-validated output; `seq` is the
|
|
95
|
+
* unit's watermark at emission (the seq of the event that caused the change).
|
|
92
96
|
*/
|
|
93
97
|
type ProjectionChangeListener = (
|
|
94
98
|
session: Session,
|
|
95
99
|
key: Extract<keyof SessionProjectionMap, string>,
|
|
96
100
|
value: unknown,
|
|
97
|
-
seq:
|
|
101
|
+
seq: SessionSeq,
|
|
98
102
|
) => void
|
|
99
103
|
```
|
|
100
104
|
|
|
101
|
-
`snapshot(session)` is fully synchronous: a carrier reads it in the same tick as its page slice, so `asOfSeq` covers both reads at one sequence number. It returns only client views, and every value passes its unit's `viewSchema` before return. `stateOf(session, key)` reads one live host state without computing unrelated views; callers must not mutate the borrowed reference.
|
|
105
|
+
`snapshot(session)` is fully synchronous: a carrier reads it in the same tick as its page slice, so `asOfSeq` covers both reads at one sequence number. It returns only client views, and every value passes its unit's `viewSchema` before return. `stateOf(session, key)` reads one live host state without computing unrelated views; callers must not mutate the borrowed reference. A state-reference change computes one cached raw view, and the change feed fires only when that result changes by `Object.is`; an object-valued view must preserve its reference to suppress publication across internal-only state changes.
|
|
102
106
|
|
|
103
107
|
## The registry: `ctx.sessionProjections`
|
|
104
108
|
|
|
@@ -128,11 +132,32 @@ The persisted projection cache service. Opens the `session_projcache` domain at
|
|
|
128
132
|
* paths (the history tail baseline) supersede these values whenever a
|
|
129
133
|
* session is actually opened.
|
|
130
134
|
* @param meta - the listed session's header (identity witness; no log read).
|
|
135
|
+
* @param inheritedEventCount - exact inherited prefix length that completes
|
|
136
|
+
* the checkpoint identity.
|
|
131
137
|
* @param keys - optional projection keys required by the caller's audience.
|
|
132
138
|
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
|
133
139
|
* `undefined` when no usable row exists for this lifecycle.
|
|
134
140
|
*/
|
|
135
|
-
cachedSnapshot( meta: SessionHeader, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined
|
|
141
|
+
cachedSnapshot( meta: SessionHeader, inheritedEventCount: SessionLogOffset, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Read only a predecessor checkpoint's title as a zero-I/O listing hint.
|
|
145
|
+
*
|
|
146
|
+
* The authoritative Session header supplies the lifecycle identity. A cache
|
|
147
|
+
* checkpoint can lag that log but cannot lead it because writes flush the
|
|
148
|
+
* log first, so a matching predecessor title is a genuine (possibly stale)
|
|
149
|
+
* fact from this Session. The registry still requires the current title
|
|
150
|
+
* projection's row version and schema. No other predecessor projection is
|
|
151
|
+
* exposed: format normalization can change their current meaning, and the
|
|
152
|
+
* strict {@link cachedSnapshot} / hydration paths continue to reject them.
|
|
153
|
+
* @param meta - authoritative listed Session header.
|
|
154
|
+
* @param inheritedEventCount - exact inherited cut completing the lifecycle identity.
|
|
155
|
+
* @returns a title-only checkpoint view with `asOfSeq: -1`, or `undefined`
|
|
156
|
+
* when the record is current, newer, unrelated, missing, or incompatible
|
|
157
|
+
* with the title unit. The sentinel avoids reusing a sequence that a
|
|
158
|
+
* cardinality-changing Session migration may have remapped.
|
|
159
|
+
*/
|
|
160
|
+
cachedPredecessorTitle( meta: SessionHeader, inheritedEventCount: SessionLogOffset, ): ProjectionSnapshot | undefined
|
|
136
161
|
|
|
137
162
|
/**
|
|
138
163
|
* Hydrate projection cells for an already-prepared Session without another
|
|
@@ -140,11 +165,10 @@ cachedSnapshot( meta: SessionHeader, keys?: readonly Extract<keyof SessionProjec
|
|
|
140
165
|
* advances every unit to the observation cut. No checkpoint is written
|
|
141
166
|
* because the logical observation may contain recovery events not yet durable.
|
|
142
167
|
* @param session - exact unpublished Session retained by persistence.
|
|
143
|
-
* @param meta - observed lifecycle header.
|
|
144
168
|
* @param events - exact logical event prefix represented by the observation.
|
|
145
169
|
* @returns all projection values at the event cut.
|
|
146
170
|
*/
|
|
147
|
-
hydratePrepared( session: Session,
|
|
171
|
+
hydratePrepared( session: Session, events: readonly SessionEvent[], ): ProjectionSnapshot
|
|
148
172
|
|
|
149
173
|
/**
|
|
150
174
|
* Durably checkpoint one live session NOW (all mandatory points call
|
|
@@ -166,13 +190,14 @@ async write(session: Session): Promise<void>
|
|
|
166
190
|
* The caller supplies the complete log in seq order: this service never
|
|
167
191
|
* consults the persistence layer.
|
|
168
192
|
* @param meta - the stored session header (identity witness).
|
|
193
|
+
* @param inheritedEventCount - exact inherited prefix length for projection initialization and identity.
|
|
169
194
|
* @param events - the session's complete log, in seq order.
|
|
170
195
|
* @returns the projection cut at the log end.
|
|
171
196
|
*/
|
|
172
|
-
coldSnapshot(meta: SessionHeader, events: readonly SessionEvent[]): ProjectionSnapshot
|
|
197
|
+
coldSnapshot( meta: SessionHeader, inheritedEventCount: SessionLogOffset, events: readonly SessionEvent[], ): ProjectionSnapshot
|
|
173
198
|
```
|
|
174
199
|
|
|
175
|
-
Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md)
|
|
200
|
+
Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md) · [SessionLogOffset](./session.md)
|
|
176
201
|
|
|
177
202
|
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)
|
|
178
203
|
|
|
@@ -180,7 +205,7 @@ Source: [`packages/session/session-projection-cache/src/index.ts`](https://githu
|
|
|
180
205
|
|
|
181
206
|
### `ctx.sessionProjections` — `SessionProjectionRegistry`
|
|
182
207
|
|
|
183
|
-
`ctx.sessionProjections`: the projection unit table and its drive. The service subscribes to `session/event` once; every committed event passes every registered unit's `apply` (eager drive)
|
|
208
|
+
`ctx.sessionProjections`: the projection unit table and its drive. The service subscribes to `session/event` once; every committed event passes every registered unit's `apply` (eager drive). A changed state reference computes the next client view; the change feed is notified only when its raw result changes by `Object.is`. 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 (disposer rides the calling fiber): an unloaded domain plugin's key disappears from snapshots and clients read it as capability absence. A host reader either declares `sessionProjections` in its plugin `inject` or fails explicitly when the registry or required key is absent. Contributors may preserve optional registration through `ctx.inject(['sessionProjections'], ...)`. Registrants sharing a key share one unit and are counted: the same tool package mounted in N agent presets registers N times, and the key survives until the last one unloads.
|
|
184
209
|
|
|
185
210
|
```ts cordis-catalog
|
|
186
211
|
/**
|
|
@@ -204,7 +229,7 @@ register< K extends Exclude<keyof SessionProjectionStateMap, keyof SessionProjec
|
|
|
204
229
|
/**
|
|
205
230
|
* Subscribe to the change feed. The registration is an effect on the
|
|
206
231
|
* calling context's fiber.
|
|
207
|
-
* @param listener - called once per client-visible unit whose
|
|
232
|
+
* @param listener - called once per client-visible unit whose raw view changed by `Object.is`, per committed event.
|
|
208
233
|
* @returns the exact disposer that unsubscribes.
|
|
209
234
|
*/
|
|
210
235
|
onChanged(listener: ProjectionChangeListener): () => void
|
|
@@ -268,11 +293,11 @@ checkpoint(session: Session): ProjectionCheckpoint
|
|
|
268
293
|
* yields an end below every watermark and the restore rejects for a full
|
|
269
294
|
* re-read.
|
|
270
295
|
* @param checkpoint - persisted rows for one session (possibly stale or empty).
|
|
271
|
-
* @returns the
|
|
272
|
-
* when no unit is registered (no read needed —
|
|
273
|
-
* serve empty values regardless).
|
|
296
|
+
* @returns the offset for the stored-log suffix read (`SessionHandle.read`),
|
|
297
|
+
* or `undefined` when no unit is registered (no read needed —
|
|
298
|
+
* {@link restore} would serve empty values regardless).
|
|
274
299
|
*/
|
|
275
|
-
restoreFloor(checkpoint: ProjectionCheckpoint):
|
|
300
|
+
restoreFloor(checkpoint: ProjectionCheckpoint): SessionLogOffset | undefined
|
|
276
301
|
|
|
277
302
|
/**
|
|
278
303
|
* View a checkpoint's rows without any log read: for every registered
|
|
@@ -291,8 +316,8 @@ viewCheckpoint( checkpoint: ProjectionCheckpoint, keys?: readonly Extract<keyof
|
|
|
291
316
|
* Cold read: fold every persisted unit over a stored log suffix, seeding
|
|
292
317
|
* each from its checkpoint row when usable — the one read recipe (cached
|
|
293
318
|
* state + forward tail replay + `view`) applied without a live `Session`.
|
|
294
|
-
* Call with the events
|
|
295
|
-
* `
|
|
319
|
+
* Call with the stored events at or past `restoreFloor(checkpoint)` (a
|
|
320
|
+
* `SessionHandle.read` slice) and that same floor as
|
|
296
321
|
* `baseSeq`; the floor's one-below anchor makes the supplied end honest,
|
|
297
322
|
* so a shrunk log is detected here. A row is usable iff its
|
|
298
323
|
* `ver` matches the live unit's `stateVersion`, it does not predate `baseSeq`
|
|
@@ -306,11 +331,12 @@ viewCheckpoint( checkpoint: ProjectionCheckpoint, keys?: readonly Extract<keyof
|
|
|
306
331
|
* @param events - the stored events with `seq >= baseSeq`, in seq order.
|
|
307
332
|
* @param baseSeq - the seq `events` starts at (its first event's seq when non-empty).
|
|
308
333
|
* @param header - immutable metadata for the Session being restored.
|
|
334
|
+
* @param inheritedEventCount - exact fork-inherited prefix length supplied to unit initialization.
|
|
309
335
|
* @returns the snapshot cut at the supplied log end (`asOfSeq` is the last
|
|
310
336
|
* supplied event's seq, `baseSeq - 1` for an empty tail) plus the
|
|
311
337
|
* refreshed checkpoint rows at that cut, ready for a durable write-back.
|
|
312
338
|
*/
|
|
313
|
-
restore( checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq:
|
|
339
|
+
restore( checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: SessionLogOffset, header: SessionHeader, inheritedEventCount: SessionLogOffset, ): { snapshot: ProjectionSnapshot; checkpoint: ProjectionCheckpoint }
|
|
314
340
|
|
|
315
341
|
/**
|
|
316
342
|
* Restore an exact cut and install its states on the supplied prepared Session.
|
|
@@ -322,10 +348,10 @@ restore( checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], base
|
|
|
322
348
|
* @param baseSeq - first supplied event sequence.
|
|
323
349
|
* @returns all projection values at the supplied cut.
|
|
324
350
|
*/
|
|
325
|
-
hydrate( session: Session, checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq:
|
|
351
|
+
hydrate( session: Session, checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: SessionLogOffset, ): ProjectionSnapshot
|
|
326
352
|
```
|
|
327
353
|
|
|
328
|
-
Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md)
|
|
354
|
+
Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md) · [SessionLogOffset](./session.md)
|
|
329
355
|
|
|
330
356
|
Source: [`packages/session/session-projection/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/src/index.ts)
|
|
331
357
|
<!-- END GENERATED cordis-surface -->
|
|
@@ -25,7 +25,7 @@ interface SessionRecord {
|
|
|
25
25
|
header: SessionHeader
|
|
26
26
|
/** Whether the id currently exists in `ctx.sessions`. */
|
|
27
27
|
live: boolean
|
|
28
|
-
/** Whether the active persistence backend currently
|
|
28
|
+
/** Whether the active persistence backend currently lists the id, including a created-but-unmaterialized session it already observes. */
|
|
29
29
|
persisted: boolean
|
|
30
30
|
}
|
|
31
31
|
```
|
|
@@ -37,7 +37,9 @@ interface SessionRecord {
|
|
|
37
37
|
interface SessionLogSnapshot {
|
|
38
38
|
/** Cloned session header selected from the same observation as `events`. */
|
|
39
39
|
session: SessionHeader
|
|
40
|
-
/**
|
|
40
|
+
/** Exact number of fork-inherited events in the observed log. */
|
|
41
|
+
inheritedEventCount: SessionLogOffset
|
|
42
|
+
/** Cloned contiguous raw events after in-memory interrupted-turn balancing and replay validation. */
|
|
41
43
|
events: SessionEvent[]
|
|
42
44
|
}
|
|
43
45
|
```
|
|
@@ -47,8 +49,10 @@ interface SessionLogSnapshot {
|
|
|
47
49
|
interface SessionSurfaceSnapshot {
|
|
48
50
|
/** Cloned session header selected from the same corpus observation as `events`. */
|
|
49
51
|
session: SessionHeader
|
|
52
|
+
/** Exact number of fork-inherited events in the observed log. */
|
|
53
|
+
inheritedEventCount: SessionLogOffset
|
|
50
54
|
/** Highest raw-log seq included in the observation, or `null` for an empty log. */
|
|
51
|
-
capturedThroughSeq:
|
|
55
|
+
capturedThroughSeq: OptionalSessionSeq
|
|
52
56
|
/** Cloned current surface events in model-history order. */
|
|
53
57
|
events: SurfaceEvent[]
|
|
54
58
|
}
|
|
@@ -93,7 +97,7 @@ interface SessionEventRecord {
|
|
|
93
97
|
/** Session that owns the event. */
|
|
94
98
|
sessionId: SessionId
|
|
95
99
|
/** Monotonic event seq within the session. */
|
|
96
|
-
seq:
|
|
100
|
+
seq: SessionSeq
|
|
97
101
|
/** Discriminant of the session event. */
|
|
98
102
|
type: SessionEventType
|
|
99
103
|
/** Event timestamp in Unix epoch milliseconds. */
|
|
@@ -269,7 +273,7 @@ interface SessionEventReadRequest {
|
|
|
269
273
|
/** Session that owns the target event. */
|
|
270
274
|
sessionId: SessionId
|
|
271
275
|
/** Target event seq. */
|
|
272
|
-
seq:
|
|
276
|
+
seq: SessionSeq
|
|
273
277
|
/** Number of preceding raw events to include. */
|
|
274
278
|
before?: number
|
|
275
279
|
/** Number of following raw events to include. */
|
|
@@ -282,14 +286,16 @@ interface SessionEventReadRequest {
|
|
|
282
286
|
interface SessionEventWindow {
|
|
283
287
|
/** Cloned header for the live-preferred source read. */
|
|
284
288
|
session: SessionHeader
|
|
289
|
+
/** Exact number of fork-inherited events in the observed log. */
|
|
290
|
+
inheritedEventCount: SessionLogOffset
|
|
285
291
|
/** Full cloned target event. */
|
|
286
292
|
target: SessionEvent
|
|
287
293
|
/** Full cloned events from `startSeq` through `endSeq`. */
|
|
288
294
|
events: SessionEvent[]
|
|
289
295
|
/** First seq included in `events`. */
|
|
290
|
-
startSeq:
|
|
296
|
+
startSeq: SessionSeq
|
|
291
297
|
/** Last seq included in `events`. */
|
|
292
|
-
endSeq:
|
|
298
|
+
endSeq: SessionSeq
|
|
293
299
|
}
|
|
294
300
|
```
|
|
295
301
|
|
|
@@ -303,7 +309,7 @@ interface SessionEventTraceRequest {
|
|
|
303
309
|
/** Session that owns the target event. */
|
|
304
310
|
sessionId: SessionId
|
|
305
311
|
/** Target event seq. */
|
|
306
|
-
seq:
|
|
312
|
+
seq: SessionSeq
|
|
307
313
|
}
|
|
308
314
|
```
|
|
309
315
|
|
|
@@ -313,15 +319,15 @@ interface SessionEventTrace {
|
|
|
313
319
|
/** Lightweight target record. */
|
|
314
320
|
target: SessionEventRecord
|
|
315
321
|
/** Immediate positional replacement event, when the target was shadowed. */
|
|
316
|
-
replacedBy?:
|
|
322
|
+
replacedBy?: SessionSeq
|
|
317
323
|
/** Positional replacers from the immediate replacement to the final replacement. */
|
|
318
|
-
replacementChain:
|
|
324
|
+
replacementChain: SessionSeq[]
|
|
319
325
|
/** Surface nodes directly removed when the target itself performed a replacement. */
|
|
320
|
-
replacedEventSeqs:
|
|
326
|
+
replacedEventSeqs: SessionSeq[]
|
|
321
327
|
/** Earlier events cited directly as sources, in their recorded order. */
|
|
322
|
-
sourceEventSeqs:
|
|
328
|
+
sourceEventSeqs: SessionSeq[]
|
|
323
329
|
/** Later events that directly cite the target as a source, in log order. */
|
|
324
|
-
derivedEventSeqs:
|
|
330
|
+
derivedEventSeqs: SessionSeq[]
|
|
325
331
|
}
|
|
326
332
|
```
|
|
327
333
|
|
|
@@ -71,7 +71,31 @@ interface SessionReferenceMentionCandidate extends SessionReferenceCandidate {
|
|
|
71
71
|
|
|
72
72
|
## Prepared messages
|
|
73
73
|
|
|
74
|
-
Preparation preserves readable current-message content and returns at most one aggregated context.
|
|
74
|
+
Preparation preserves readable current-message content and returns at most one aggregated context. Its durable source records keep `capturedThroughSeq` as a coordinate in the referenced Session's original generation; they never reinterpret it as a seq in the containing Session. `capturedFormatVersion` records that generation, with absence meaning released format v0.
|
|
75
|
+
|
|
76
|
+
```ts type-equiv
|
|
77
|
+
/** Durable source session, cited event seqs, and snapshot facts for prepared cross-session context. */
|
|
78
|
+
interface SessionReferenceSource {
|
|
79
|
+
kind: 'session-reference'
|
|
80
|
+
/** Material lifted out of another session's log (`recall` context form). */
|
|
81
|
+
form: 'recall'
|
|
82
|
+
version: 1
|
|
83
|
+
references: {
|
|
84
|
+
sessionId: string
|
|
85
|
+
label: string
|
|
86
|
+
/** Source Session format generation; absence identifies version 0. */
|
|
87
|
+
capturedFormatVersion?: number
|
|
88
|
+
capturedThroughSeq: OptionalSessionSeq
|
|
89
|
+
compacted: boolean
|
|
90
|
+
originalMessages: number
|
|
91
|
+
retainedMessages: number
|
|
92
|
+
omittedMessages: number
|
|
93
|
+
omittedBytes: number
|
|
94
|
+
truncated: boolean
|
|
95
|
+
inputIndex: number
|
|
96
|
+
}[]
|
|
97
|
+
}
|
|
98
|
+
```
|
|
75
99
|
|
|
76
100
|
```ts type-equiv
|
|
77
101
|
/** Direct message content and optional referenced-session context. */
|
|
@@ -183,6 +207,10 @@ async listCandidates( agent: Agent, query: string = '', limit: number = this.con
|
|
|
183
207
|
|
|
184
208
|
/**
|
|
185
209
|
* Snapshot all references for one accepted direct message and return one aggregated durable context.
|
|
210
|
+
* Automatic budgets use the last assembled route, or agent options before any assembly.
|
|
211
|
+
* Missing model capacity or adapter uses 64 KiB; other metadata lookup failures and cancellation reject preparation.
|
|
212
|
+
* Truncated previews include omission facts and a full-snapshot spill locator, or an explicit unavailable notice.
|
|
213
|
+
* Cancellation prevents context publication, including when storage completes after cancellation.
|
|
186
214
|
* @param agent - target agent; references to it are rejected.
|
|
187
215
|
* @param content - already host-normalized readable message content.
|
|
188
216
|
* @param references - structured source sessions in mention order.
|
|
@@ -5,7 +5,7 @@ outline: [2,3]
|
|
|
5
5
|
|
|
6
6
|
# SessionTelemetryBackend
|
|
7
7
|
|
|
8
|
-
Outbound session reporting is split as a [capability seam](../capability-seams.md): the Service Definition and capture coordinator ([dsh-session-telemetry](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-telemetry), `ctx.sessionTelemetry`) own
|
|
8
|
+
Outbound session reporting is split as a [capability seam](../capability-seams.md): the Service Definition and capture coordinator ([dsh-session-telemetry](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-telemetry), `ctx.sessionTelemetry`) own complete canonical-event capture, the `session-telemetry/record` redaction waterfall, the handoff cursor, and the minimal backend contract; the Service Provider a deployment loads ([dsh-session-telemetry-otel](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-telemetry-otel)) is the OpenTelemetry JS SDK's log pipeline configured verbatim. It is one optional capability, not part of the agent-loop spine, and nothing here reaches a model request. The boundary axiom — the harness's aspect ends at `emit()`; batching, retry, queueing, and loss policy belong to the reporting SDK — and the rejected alternatives are pinned in the [revival Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.md); the capture and cursor contracts live in the [Service Definition README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-telemetry/README.md).
|
|
9
9
|
|
|
10
10
|
Source: [`packages/session/session-telemetry/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-telemetry/src/index.ts)
|
|
11
11
|
|
|
@@ -40,8 +40,9 @@ interface SessionTelemetryRecord {
|
|
|
40
40
|
severity: SessionTelemetrySeverity
|
|
41
41
|
/**
|
|
42
42
|
* Identity attributes, deliberately minimal: ledger records carry
|
|
43
|
-
* `session.id`, `event.type`, `event.seq`, plus
|
|
44
|
-
* `session.
|
|
43
|
+
* `session.id`, `session.format_version`, `event.type`, `event.seq`, plus optional
|
|
44
|
+
* `session.cwd` / `session.parent_id`; a seeded Session also carries
|
|
45
|
+
* `session.seed_length` from its exact inherited event count;
|
|
45
46
|
* ops records carry `telemetry.op`, `session.id`, and (for `agent-error`)
|
|
46
47
|
* `agent.id`, `turn`, `step`, `error.name`. Anything recoverable from the
|
|
47
48
|
* body is intentionally NOT duplicated here.
|
|
@@ -57,22 +58,38 @@ interface SessionTelemetryRecord {
|
|
|
57
58
|
}
|
|
58
59
|
```
|
|
59
60
|
|
|
60
|
-
|
|
61
|
+
Every canonical [session event](./session.md), including each `assistant/message` or `assistant/attempt` with its complete compact stream and every plugin-merged type the seam never heard of, passes through whole as one ordered ledger record. Process-local `agent/assistant-stream` frames do not enter this durable feed. A new Session object starts at its lifecycle boundary unless the backend selects `includeHistory`; re-adopting the same object resumes after its handoff cursor. Delivery is best-effort: the cursor marks handed-off, not delivered, and records can be lost (crash, reload window) or duplicated (new-object replay, SDK retries), so receivers dedupe ledger records on `(session.id, session.format_version, event.seq)`; ops records deliberately omit that identity — they are signals to alert on, not entries to sum, and tolerate duplicates instead.
|
|
61
62
|
|
|
62
63
|
## The sharing disclosure
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
Every backend exposes its deployment-selected mode through the required abstract `sharing` member on `ctx.sessionTelemetry` ([Service Definition README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-telemetry/README.md#the-sharing-disclosure)). This is neither a per-Session admission decision nor a delivery receipt. The `/feedback` acknowledgement does not consult it.
|
|
65
66
|
|
|
66
67
|
```ts type-equiv
|
|
67
68
|
/**
|
|
68
|
-
* Deployment-selected session-sharing
|
|
69
|
-
* {@link SessionTelemetryBackend} backend to human-facing acknowledgement surfaces (the
|
|
70
|
-
* `/feedback` command's confirmation text). The Service Definition owns the
|
|
71
|
-
* vocabulary so consumers and backends do not depend on a specific provider.
|
|
69
|
+
* Deployment-selected session-sharing mode, not confirmation of SDK delivery.
|
|
72
70
|
*/
|
|
73
71
|
type SessionTelemetrySharingStatus = 'full' | 'feedback-only' | 'disabled'
|
|
74
72
|
```
|
|
75
73
|
|
|
74
|
+
## Capture policy
|
|
75
|
+
|
|
76
|
+
```ts type-equiv
|
|
77
|
+
/** Whether capture follows live events or reads the canonical log only when requested. */
|
|
78
|
+
type SessionTelemetryCapture = 'live' | 'on-demand'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```ts type-equiv
|
|
82
|
+
/** Backend-selected capture mode and history policy. */
|
|
83
|
+
interface SessionTelemetryCaptureOptions {
|
|
84
|
+
/** Follow live events, or wait for explicit capture; defaults to live. */
|
|
85
|
+
capture?: SessionTelemetryCapture
|
|
86
|
+
/** Include stored history before this lifecycle; defaults to false. */
|
|
87
|
+
includeHistory?: boolean
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`includeHistory` permits stored and inherited records but does not itself authorize capture. The [OTel backend](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-telemetry-otel/README.md) uses on-demand capture and requires new own explicit feedback; it releases only the complete prefix through that feedback, for every provider.
|
|
92
|
+
|
|
76
93
|
## The backend contract
|
|
77
94
|
|
|
78
95
|
```ts type-equiv
|
|
@@ -125,7 +142,7 @@ interface SessionTelemetrySink {
|
|
|
125
142
|
|
|
126
143
|
## The redact waterfall: `session-telemetry/record`
|
|
127
144
|
|
|
128
|
-
Every record passes the `session-telemetry/record` [waterfall](../cordis-primer.md#cordis-waterfall-semantics) between
|
|
145
|
+
Every record passes the `session-telemetry/record` [waterfall](../cordis-primer.md#cordis-waterfall-semantics) between the canonical-event copy and `emit()` ([event entry](#session-telemetryrecord--waterfall)). The seam ships NO rules of its own: with no listener mounted, records reach the backend exactly as captured, so exported data is precisely as clean as the rules a deployment mounts. Listeners stack by transforming `next()`'s return value; returning without `next()` replaces everything beneath; a throwing listener withholds that one record fail-closed inside the coordinator's containment. Redaction applies to the exported copy only — the canonical session log is never rewritten.
|
|
129
146
|
|
|
130
147
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
131
148
|
|
|
@@ -11,7 +11,7 @@ Sources: [`packages/session/session-title/src/index.ts`](https://github.com/deep
|
|
|
11
11
|
|
|
12
12
|
## Durable title state
|
|
13
13
|
|
|
14
|
-
`SessionTitleProviderId` is recorded for provider-produced revisions. `SessionTitleEventData` lists the exact human-message seqs used for the title, while `SessionTitleSnapshot` adds the durable event envelope facts
|
|
14
|
+
`SessionTitleProviderId` is recorded for provider-produced revisions. `SessionTitleEventData` lists the exact human-message seqs used for the title, while `SessionTitleSnapshot` adds the durable event envelope facts returned by `ctx.sessionTitle.get()` and `foldSessionTitle()`. The `title` projection keeps its version-1 state and client view as only the title string or `null`, so existing persisted cache rows remain readable.
|
|
15
15
|
|
|
16
16
|
```ts type-equiv
|
|
17
17
|
/** Identifies one session-title provider registration. */
|
|
@@ -49,7 +49,7 @@ interface SessionTitleEventData {
|
|
|
49
49
|
/** Normalized non-empty title text. */
|
|
50
50
|
readonly title: string
|
|
51
51
|
/** Exact human `user/message` seqs used to derive this title; empty for an explicit user rename. */
|
|
52
|
-
readonly messageSeqs:
|
|
52
|
+
readonly messageSeqs: SessionSeq[]
|
|
53
53
|
/** Whether the built-in fallback, a registered provider, or the user supplied the title. */
|
|
54
54
|
readonly source: SessionTitleSource
|
|
55
55
|
}
|
|
@@ -59,7 +59,7 @@ interface SessionTitleEventData {
|
|
|
59
59
|
/** Latest folded title plus the title event's durable envelope facts. */
|
|
60
60
|
interface SessionTitleSnapshot extends SessionTitleEventData {
|
|
61
61
|
/** Seq of the latest `session/title` event. */
|
|
62
|
-
readonly eventSeq:
|
|
62
|
+
readonly eventSeq: SessionSeq
|
|
63
63
|
/** Timestamp of the latest `session/title` event. */
|
|
64
64
|
readonly updatedAt: number
|
|
65
65
|
}
|
|
@@ -75,7 +75,7 @@ interface SessionTitleLlmRequestEventData {
|
|
|
75
75
|
/** Registered title-provider identity responsible for the request. */
|
|
76
76
|
readonly titleProvider: SessionTitleProviderId
|
|
77
77
|
/** Exact human `user/message` seqs represented in `messages`. */
|
|
78
|
-
readonly messageSeqs:
|
|
78
|
+
readonly messageSeqs: SessionSeq[]
|
|
79
79
|
/** Exact auxiliary LLM route. */
|
|
80
80
|
readonly route: SessionTitleModelProvenance
|
|
81
81
|
/** Exact auxiliary system prompt. */
|
|
@@ -95,7 +95,7 @@ The service snapshots eligible messages through one revision. A provider returns
|
|
|
95
95
|
/** One eligible human text message exposed to title providers. */
|
|
96
96
|
interface SessionTitleUserMessage {
|
|
97
97
|
/** Source `user/message` event seq. */
|
|
98
|
-
readonly seq:
|
|
98
|
+
readonly seq: SessionSeq
|
|
99
99
|
/** Exact concatenated text-block content. */
|
|
100
100
|
readonly text: string
|
|
101
101
|
}
|
|
@@ -126,7 +126,7 @@ interface SessionTitleProviderResult {
|
|
|
126
126
|
/** Proposed title text. */
|
|
127
127
|
readonly title: string
|
|
128
128
|
/** Exact seqs from `request.messages` used by this result. */
|
|
129
|
-
readonly messageSeqs: readonly
|
|
129
|
+
readonly messageSeqs: readonly SessionSeq[]
|
|
130
130
|
/** Auxiliary LLM route, when generation used a model. */
|
|
131
131
|
readonly model?: SessionTitleModelProvenance
|
|
132
132
|
}
|