dsh-plugin-guide 0.3.2 → 0.3.4
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/README.es.md +5 -1
- package/README.hi.md +5 -1
- package/README.md +5 -1
- package/README.pt.md +5 -1
- package/README.zh.md +5 -1
- package/dist/dsh-plugin-dev.js +3 -3
- package/guide/plugin-dev-guide.md +2 -2
- package/guide/quick-reference.es.md +2 -2
- package/guide/quick-reference.hi.md +1 -1
- package/guide/quick-reference.md +2 -2
- package/guide/quick-reference.pt.md +2 -2
- package/guide/quick-reference.zh-CN.md +2 -2
- package/package.json +3 -3
- package/references/official-docs/AGENTS.md +3 -3
- package/references/official-docs/SNAPSHOT.md +4 -4
- package/references/official-docs/THIRD_PARTY_NOTICES.md +4 -6
- package/references/official-docs/docs/agent-lifecycle.i18n.yaml +2 -2
- package/references/official-docs/docs/agent-lifecycle.md +5 -3
- package/references/official-docs/docs/agent-lifecycle.zh.md +5 -3
- package/references/official-docs/docs/architecture.i18n.yaml +2 -2
- package/references/official-docs/docs/architecture.md +9 -4
- package/references/official-docs/docs/architecture.zh.md +9 -4
- package/references/official-docs/docs/capability-seams.i18n.yaml +2 -2
- package/references/official-docs/docs/capability-seams.md +8 -1
- package/references/official-docs/docs/capability-seams.zh.md +8 -1
- package/references/official-docs/docs/config-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/config-catalog.md +104 -68
- package/references/official-docs/docs/config-catalog.zh.md +101 -65
- package/references/official-docs/docs/cookbook/adding-a-package.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/adding-a-package.md +1 -1
- package/references/official-docs/docs/cookbook/adding-a-package.zh.md +1 -1
- package/references/official-docs/docs/cookbook/extension-cookbook.i18n.yaml +2 -2
- package/references/official-docs/docs/cookbook/extension-cookbook.md +12 -10
- package/references/official-docs/docs/cookbook/extension-cookbook.zh.md +12 -10
- package/references/official-docs/docs/deepseek-llm-api-wire-extensions.i18n.yaml +2 -2
- package/references/official-docs/docs/deepseek-llm-api-wire-extensions.md +16 -12
- package/references/official-docs/docs/deepseek-llm-api-wire-extensions.zh.md +16 -12
- package/references/official-docs/docs/event-producer-consumer.i18n.yaml +2 -2
- package/references/official-docs/docs/event-producer-consumer.md +30 -29
- package/references/official-docs/docs/event-producer-consumer.zh.md +35 -34
- package/references/official-docs/docs/module-graph.i18n.yaml +2 -2
- package/references/official-docs/docs/module-graph.md +214 -360
- package/references/official-docs/docs/module-graph.zh.md +214 -360
- package/references/official-docs/docs/persistence-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/persistence-catalog.md +74 -64
- package/references/official-docs/docs/persistence-catalog.zh.md +72 -62
- package/references/official-docs/docs/subsystems/agent-team.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/agent-team.md +4 -3
- package/references/official-docs/docs/subsystems/agent-team.zh.md +4 -3
- package/references/official-docs/docs/subsystems/attachment.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/attachment.md +157 -4
- package/references/official-docs/docs/subsystems/attachment.zh.md +157 -4
- package/references/official-docs/docs/subsystems/code-runtime.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/code-runtime.md +7 -3
- package/references/official-docs/docs/subsystems/code-runtime.zh.md +7 -3
- package/references/official-docs/docs/subsystems/commands.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/commands.md +25 -16
- package/references/official-docs/docs/subsystems/commands.zh.md +25 -16
- package/references/official-docs/docs/subsystems/compaction.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/compaction.md +9 -9
- package/references/official-docs/docs/subsystems/compaction.zh.md +9 -9
- package/references/official-docs/docs/subsystems/conversation.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/conversation.md +4 -4
- package/references/official-docs/docs/subsystems/conversation.zh.md +4 -4
- package/references/official-docs/docs/subsystems/core.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/core.md +66 -4
- package/references/official-docs/docs/subsystems/core.zh.md +66 -4
- package/references/official-docs/docs/subsystems/feedback.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/feedback.md +2 -2
- package/references/official-docs/docs/subsystems/feedback.zh.md +2 -2
- package/references/official-docs/docs/subsystems/llm-streaming.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/llm-streaming.md +23 -2
- package/references/official-docs/docs/subsystems/llm-streaming.zh.md +23 -2
- package/references/official-docs/docs/subsystems/persistence.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/persistence.md +183 -191
- package/references/official-docs/docs/subsystems/persistence.zh.md +183 -191
- package/references/official-docs/docs/subsystems/schedule.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/schedule.md +1 -1
- package/references/official-docs/docs/subsystems/schedule.zh.md +1 -1
- package/references/official-docs/docs/subsystems/session-projection.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-projection.md +40 -17
- package/references/official-docs/docs/subsystems/session-projection.zh.md +40 -17
- package/references/official-docs/docs/subsystems/session-query.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-query.md +19 -13
- package/references/official-docs/docs/subsystems/session-query.zh.md +19 -13
- package/references/official-docs/docs/subsystems/session-reference.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-reference.md +25 -1
- package/references/official-docs/docs/subsystems/session-reference.zh.md +25 -1
- package/references/official-docs/docs/subsystems/session-telemetry.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-telemetry.md +6 -5
- package/references/official-docs/docs/subsystems/session-telemetry.zh.md +6 -5
- package/references/official-docs/docs/subsystems/session-title.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session-title.md +5 -5
- package/references/official-docs/docs/subsystems/session-title.zh.md +5 -5
- package/references/official-docs/docs/subsystems/session.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/session.md +143 -71
- package/references/official-docs/docs/subsystems/session.zh.md +143 -71
- package/references/official-docs/docs/subsystems/slots.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/slots.md +1 -0
- package/references/official-docs/docs/subsystems/slots.zh.md +1 -0
- package/references/official-docs/docs/subsystems/storage.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/storage.md +28 -5
- package/references/official-docs/docs/subsystems/storage.zh.md +28 -5
- package/references/official-docs/docs/subsystems/subagent.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/subagent.md +32 -88
- package/references/official-docs/docs/subsystems/subagent.zh.md +31 -87
- package/references/official-docs/docs/subsystems/token-meter.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/token-meter.md +2 -2
- package/references/official-docs/docs/subsystems/token-meter.zh.md +2 -2
- package/references/official-docs/docs/subsystems/web-client.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/web-client.md +1 -1
- package/references/official-docs/docs/subsystems/web-client.zh.md +1 -1
- package/references/official-docs/docs/subsystems/workspace.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/workspace.md +8 -8
- package/references/official-docs/docs/subsystems/workspace.zh.md +8 -8
- package/references/official-docs/docs/testing.i18n.yaml +2 -2
- package/references/official-docs/docs/testing.md +2 -2
- package/references/official-docs/docs/testing.zh.md +2 -2
- package/references/official-docs/docs/tool-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/tool-catalog.md +9 -63
- package/references/official-docs/docs/tool-catalog.zh.md +8 -62
- package/references/official-docs/docs/user/guide/network-proxy.i18n.yaml +6 -0
- package/references/official-docs/docs/user/guide/network-proxy.md +85 -0
- package/references/official-docs/docs/user/guide/network-proxy.zh.md +85 -0
- package/references/official-docs/docs/user/guide/providers.i18n.yaml +2 -2
- package/references/official-docs/docs/user/guide/providers.md +70 -17
- package/references/official-docs/docs/user/guide/providers.zh.md +70 -17
- package/references/official-docs/docs/web-styling.i18n.yaml +2 -2
- package/references/official-docs/docs/web-styling.md +4 -0
- package/references/official-docs/docs/web-styling.zh.md +4 -0
- package/references/official-docs/packages/AGENTS.md +2 -2
- package/references/official-docs/website-docs.ts +8 -0
- package/templates/js/README.es.md +1 -1
- package/templates/js/README.hi.md +1 -1
- package/templates/js/README.md +1 -1
- package/templates/js/README.pt.md +1 -1
- package/templates/js/README.zh.md +1 -1
- package/templates/ts/README.es.md +1 -1
- package/templates/ts/README.hi.md +1 -1
- package/templates/ts/README.md +1 -1
- package/templates/ts/README.pt.md +1 -1
- package/templates/ts/README.zh.md +1 -1
|
@@ -21,8 +21,8 @@ interface UserMessage extends Message {
|
|
|
21
21
|
/**
|
|
22
22
|
* The merge-extensible, append-only source of truth for an agent interaction.
|
|
23
23
|
* Message history is derived from this log. Every event is lossless JSON and
|
|
24
|
-
* sequence numbers stay contiguous
|
|
25
|
-
*
|
|
24
|
+
* sequence numbers stay contiguous. Assistant attempt events embed their exact
|
|
25
|
+
* compact raw streams so persistence stores one durable settlement per attempt.
|
|
26
26
|
*/
|
|
27
27
|
interface SessionEventMap {
|
|
28
28
|
/**
|
|
@@ -53,8 +53,6 @@ interface SessionEventMap {
|
|
|
53
53
|
* project their `content` verbatim; `source` tells them apart.
|
|
54
54
|
*/
|
|
55
55
|
'user/message': UserMessage
|
|
56
|
-
/** Raw stream chunk — token-level replay fidelity. */
|
|
57
|
-
'assistant/chunk': { turn: number; step: number; chunk: StreamChunk }
|
|
58
56
|
/**
|
|
59
57
|
* Assembled assistant message for one step (derived history uses this).
|
|
60
58
|
* Carries the step's `usage` when the adapter reported token accounting, so
|
|
@@ -65,7 +63,21 @@ interface SessionEventMap {
|
|
|
65
63
|
* marker distinguishes that prefix without re-deriving interruption from turn
|
|
66
64
|
* boundaries. An aborted turn with no such event streamed no visible content.
|
|
67
65
|
*/
|
|
68
|
-
'assistant/message': {
|
|
66
|
+
'assistant/message': {
|
|
67
|
+
turn: number
|
|
68
|
+
step: number
|
|
69
|
+
message: AssistantMessage
|
|
70
|
+
/** Exact timed model stream, compacted without joining delta boundaries. */
|
|
71
|
+
stream: AssistantStreamRecord[]
|
|
72
|
+
usage?: TokenUsage
|
|
73
|
+
interrupted?: true
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* One model attempt that committed no surface message. The embedded stream
|
|
77
|
+
* preserves a failed, retried, cancelled, or stream-error attempt that
|
|
78
|
+
* reached settlement without fabricating model-visible history.
|
|
79
|
+
*/
|
|
80
|
+
'assistant/attempt': { turn: number; step: number; stream: AssistantStreamRecord[] }
|
|
69
81
|
/**
|
|
70
82
|
* The model requested one tool invocation: `name` with the raw `arguments`
|
|
71
83
|
* JSON string exactly as the model produced it (unparsed). `callId` pairs the
|
|
@@ -109,12 +121,12 @@ interface SessionEventMap {
|
|
|
109
121
|
* Marks the end of a constructor seed. Events before it have smaller seq
|
|
110
122
|
* values and came from the seed (resume, fork, or replay); this lifecycle
|
|
111
123
|
* produced none of them. This log-only event is the durable projection of
|
|
112
|
-
* {@link Session.firstLiveSeq}.
|
|
113
|
-
* carry the meaning.
|
|
124
|
+
* {@link Session.firstLiveSeq}.
|
|
114
125
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
126
|
+
* A fresh fork child owns one `{ inherited: true }` marker at its exact
|
|
127
|
+
* inherited-prefix cut, even when that prefix ends in an ancestor marker.
|
|
128
|
+
* The last tagged marker is the current Session's cut; untagged markers keep
|
|
129
|
+
* ordinary restore and replay lifecycle boundaries.
|
|
118
130
|
*
|
|
119
131
|
* `Session`'s constructor is the only legitimate writer. The invariant
|
|
120
132
|
* companion deliberately constrains nothing here, so a plugin appending one
|
|
@@ -127,7 +139,7 @@ interface SessionEventMap {
|
|
|
127
139
|
* writers — a concurrently live session holds its own boundary elsewhere,
|
|
128
140
|
* so tolerating concurrent writers needs a signal beyond the log.
|
|
129
141
|
*/
|
|
130
|
-
'session/end-seed':
|
|
142
|
+
'session/end-seed': { inherited?: true }
|
|
131
143
|
}
|
|
132
144
|
```
|
|
133
145
|
|
|
@@ -179,6 +191,28 @@ interface RequestContext {
|
|
|
179
191
|
|
|
180
192
|
A proper discriminated union over `type` (not independent `type`/`data` unions), so `switch (event.type)` narrows `event.data` without casts. `seq` is the monotonic position in the log (`seq = log.length`); `time` is epoch ms.
|
|
181
193
|
|
|
194
|
+
```ts type-equiv
|
|
195
|
+
/** Sequence number of one existing event in a Session log. */
|
|
196
|
+
type SessionSeq = BrandedNumber<'SessionSeq'>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```ts type-equiv
|
|
200
|
+
/** A Session log gap, prefix length, or read offset, which may equal the event count. */
|
|
201
|
+
type SessionLogOffset = BrandedNumber<'SessionLogOffset'>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```ts type-equiv
|
|
205
|
+
/** Inclusive Session event watermark, or `-1` before any event exists. */
|
|
206
|
+
type SessionSeqCursor = SessionSeq | -1
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```ts type-equiv
|
|
210
|
+
/** One existing Session event position, or explicit absence. */
|
|
211
|
+
type OptionalSessionSeq = SessionSeq | null
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
`SessionSeq(value)` and `SessionLogOffset(value)` admit only non-negative safe integers and reject negative zero. They add compile-time brands without changing the serialized number; arithmetic returns an ordinary `number` that callers must admit again through the constructor for its intended role.
|
|
215
|
+
|
|
182
216
|
```ts type-equiv
|
|
183
217
|
/**
|
|
184
218
|
* One immutable entry in the session log.
|
|
@@ -189,7 +223,7 @@ A proper discriminated union over `type` (not independent `type`/`data` unions),
|
|
|
189
223
|
* The {@link sourceEventSeqs} and {@link surfaceOp} fields are conditional:
|
|
190
224
|
* they only exist on {@link SurfaceEventType} variants (`user/message`,
|
|
191
225
|
* `assistant/message`, `tool/result`).
|
|
192
|
-
* Non-surface events (boundary markers,
|
|
226
|
+
* Non-surface events (boundary markers, attempts, errors) never carry
|
|
193
227
|
* surface metadata — the compiler enforces this at `Session.append()`
|
|
194
228
|
* call sites.
|
|
195
229
|
*/
|
|
@@ -197,7 +231,7 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
|
|
197
231
|
[K in SessionEventType]: {
|
|
198
232
|
type: K
|
|
199
233
|
/** Monotonic sequence number within the session. */
|
|
200
|
-
seq:
|
|
234
|
+
seq: SessionSeq
|
|
201
235
|
/** Unix epoch milliseconds. */
|
|
202
236
|
time: number
|
|
203
237
|
data: SessionEventMap[K]
|
|
@@ -214,14 +248,11 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
|
|
214
248
|
ignorable?: true
|
|
215
249
|
} & (K extends SurfaceEventType ? {
|
|
216
250
|
/**
|
|
217
|
-
* Seq numbers of earlier events that this event cites as sources
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* `assistant/message` may carry a present empty array for a known empty
|
|
221
|
-
* provider stream; when the field is absent, the event does not record which
|
|
222
|
-
* earlier events produced the message.
|
|
251
|
+
* Seq numbers of earlier events that this event cites as sources, such as
|
|
252
|
+
* the surface nodes shadowed by a compaction replacement. A v2
|
|
253
|
+
* `assistant/message` embeds its provider stream and cannot carry this field.
|
|
223
254
|
*/
|
|
224
|
-
sourceEventSeqs?:
|
|
255
|
+
sourceEventSeqs?: SessionSeq[]
|
|
225
256
|
/** How this event entered the surface; absent for non-surface events. */
|
|
226
257
|
surfaceOp?: SurfaceOp
|
|
227
258
|
} : object)
|
|
@@ -230,7 +261,7 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
|
|
230
261
|
|
|
231
262
|
`SessionEventType = keyof SessionEventMap`. Because `SessionEventMap` is merge-extensible, switches over `SessionEvent` must NOT use `assertNever` — a plugin-added variant is a valid unknown value; handle the known cases and fall through `default`.
|
|
232
263
|
|
|
233
|
-
|
|
264
|
+
V2 `assistant/message` embeds its provider stream and cannot carry `sourceEventSeqs`. User and tool surface events may cite a complete non-empty set of unique earlier events when their provenance or replacement operation requires it.
|
|
234
265
|
|
|
235
266
|
## Surface types
|
|
236
267
|
|
|
@@ -242,7 +273,8 @@ The three message-producing types (`SurfaceEventType` — `user/message`, `assis
|
|
|
242
273
|
/**
|
|
243
274
|
* The subset of {@link SessionEventType} values whose events produce LLM
|
|
244
275
|
* messages and are eligible to appear on the ordered surface. Only these
|
|
245
|
-
* event types may carry {@link SurfaceOp} and
|
|
276
|
+
* event types may carry {@link SurfaceOp}; user and tool events may also cite
|
|
277
|
+
* earlier sources through {@link SessionEvent.sourceEventSeqs}.
|
|
246
278
|
*/
|
|
247
279
|
type SurfaceEventType =
|
|
248
280
|
| 'user/message'
|
|
@@ -268,7 +300,7 @@ type SurfaceEventType =
|
|
|
268
300
|
*/
|
|
269
301
|
type SurfaceOp =
|
|
270
302
|
| 'append'
|
|
271
|
-
| { op: 'replace'; start:
|
|
303
|
+
| { op: 'replace'; start: SessionSeq; end: SessionSeq }
|
|
272
304
|
```
|
|
273
305
|
|
|
274
306
|
`'append'` is the normal tail-append path. `replace` shadows surface entries from `start` through `end` inclusive (both must be valid surface seqs; `start === end` replaces a single entry) and inserts the new event in their place.
|
|
@@ -280,21 +312,20 @@ type SurfaceOp =
|
|
|
280
312
|
* Surface placement and cited source-event seqs for {@link Session.append}. Required on
|
|
281
313
|
* message-producing events and forbidden on log-only events.
|
|
282
314
|
*/
|
|
283
|
-
|
|
315
|
+
type SurfaceIntent<T extends SurfaceEventType = SurfaceEventType> = {
|
|
284
316
|
surfaceOp: SurfaceOp
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
317
|
+
} & (T extends 'assistant/message' ? {
|
|
318
|
+
/** V2 Assistant messages embed their provider stream instead of citing source events. */
|
|
319
|
+
sourceEventSeqs?: never
|
|
320
|
+
} : {
|
|
321
|
+
/** Complete non-empty set of known earlier source-event seqs. */
|
|
322
|
+
sourceEventSeqs?: SessionSeq[]
|
|
323
|
+
})
|
|
293
324
|
```
|
|
294
325
|
|
|
295
326
|
Required for `SurfaceEventType` events — every message-producing event must declare how it joins the surface, the sole source of derived model history. A human-facing transcript is the other projection and reads the log's append-origin events instead, because the surface deliberately shadows the ranges a replacement summarizes (`isAppendSurfaceEvent` in [dsh-session](../../packages/core/session/README.md)). Non-surface types reject it at compile time.
|
|
296
327
|
|
|
297
|
-
|
|
328
|
+
`assistant/message` cannot carry `sourceEventSeqs`; its `stream` owns exact provider evidence. Other surface events omit the field when they cite no earlier event and use a complete non-empty list when they do.
|
|
298
329
|
|
|
299
330
|
### `SessionSurface` — the live readonly surface projection
|
|
300
331
|
|
|
@@ -306,7 +337,7 @@ Only `assistant/message` may carry a present empty `sourceEventSeqs`; when the f
|
|
|
306
337
|
/** Readonly live projection of the message-producing session events. */
|
|
307
338
|
interface SessionSurface {
|
|
308
339
|
/** Current surface event sequences in model-visible order. */
|
|
309
|
-
readonly nodes: readonly
|
|
340
|
+
readonly nodes: readonly SessionSeq[]
|
|
310
341
|
/** Monotonic count of committed positional replacements. */
|
|
311
342
|
readonly replaceGeneration: number
|
|
312
343
|
}
|
|
@@ -320,13 +351,13 @@ interface SessionSurface {
|
|
|
320
351
|
/** One replacement operation observed while folding a session surface. */
|
|
321
352
|
interface SurfaceFoldReplacement {
|
|
322
353
|
/** Seq of the event that replaced the prior surface range. */
|
|
323
|
-
seq:
|
|
354
|
+
seq: SessionSeq
|
|
324
355
|
/** Declared inclusive start seq of the replaced surface range. */
|
|
325
|
-
start:
|
|
356
|
+
start: SessionSeq
|
|
326
357
|
/** Declared inclusive end seq of the replaced surface range. */
|
|
327
|
-
end:
|
|
358
|
+
end: SessionSeq
|
|
328
359
|
/** Actual surface entries removed by the operation, in surface order. */
|
|
329
|
-
shadowedSeqs:
|
|
360
|
+
shadowedSeqs: SessionSeq[]
|
|
330
361
|
}
|
|
331
362
|
```
|
|
332
363
|
|
|
@@ -334,7 +365,7 @@ interface SurfaceFoldReplacement {
|
|
|
334
365
|
/** Complete result of replaying the surface operations in a session log. */
|
|
335
366
|
interface SurfaceFoldResult {
|
|
336
367
|
/** Current surface event sequences in model-visible order. */
|
|
337
|
-
nodes:
|
|
368
|
+
nodes: SessionSeq[]
|
|
338
369
|
/** Replacement operations in event order. */
|
|
339
370
|
replacements: SurfaceFoldReplacement[]
|
|
340
371
|
}
|
|
@@ -358,24 +389,27 @@ declare class Session {
|
|
|
358
389
|
get surface(): SessionSurface;
|
|
359
390
|
/**
|
|
360
391
|
* Detached, deep-frozen creation metadata (format version, cwd, lineage,
|
|
361
|
-
*
|
|
392
|
+
* and whether fork history exists). Supplied by the store via `ctx.sessions.create()`. When a
|
|
362
393
|
* `Session` is created without a store-owned header, a minimal header is
|
|
363
394
|
* synthesized (stamped with the current {@link SESSION_FORMAT_VERSION}) so
|
|
364
395
|
* `session.header` is always present. Kept out of the event log — it is a
|
|
365
396
|
* storage concern, not replayable conversation state.
|
|
366
397
|
*/
|
|
367
398
|
readonly header: SessionHeader;
|
|
399
|
+
/** Number of leading events inherited from this Session's fork parent. */
|
|
400
|
+
readonly inheritedEventCount: SessionLogOffset;
|
|
368
401
|
/** The session identity, derived from its durable header's single copy. */
|
|
369
402
|
get id(): SessionId;
|
|
370
403
|
/**
|
|
371
404
|
* The first seq appended IN THIS PROCESS: the length of the constructor
|
|
372
405
|
* seed (0 without one). Events with smaller seq values entered through
|
|
373
406
|
* construction — replay, fork, or resume — and were never published on the
|
|
374
|
-
* `session/event` firehose (constructor seeds do not emit)
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
407
|
+
* `session/event` firehose (constructor seeds do not emit). This offset marks
|
|
408
|
+
* the constructor-input boundary for lifecycle ownership and persistence
|
|
409
|
+
* adoption; consumers that need complete canonical history still start at
|
|
410
|
+
* seq 0. Distinct from {@link inheritedEventCount}, the DURABLE
|
|
411
|
+
* fork-lineage cut: a resumed session's constructor seed is its full stored
|
|
412
|
+
* log, while the inherited count keeps the original fork value — this field is the
|
|
379
413
|
* in-process construction fact.
|
|
380
414
|
*
|
|
381
415
|
* Not persisted itself: a seeded session projects it into the log as the
|
|
@@ -388,17 +422,23 @@ declare class Session {
|
|
|
388
422
|
* When this lifecycle appends the marker, it occupies this seq before the
|
|
389
423
|
* store attaches and therefore does not publish either. Otherwise this seq
|
|
390
424
|
* holds an ordinary published write.
|
|
391
|
-
|
|
392
|
-
readonly firstLiveSeq:
|
|
425
|
+
*/
|
|
426
|
+
readonly firstLiveSeq: SessionLogOffset;
|
|
393
427
|
/**
|
|
394
428
|
* Create a detached session by validating and snapshotting borrowed seed
|
|
395
429
|
* events and storage metadata.
|
|
396
430
|
* @param id - session identity.
|
|
397
431
|
* @param seed - optional borrowed replay or fork events.
|
|
398
432
|
* @param header - optional borrowed storage metadata.
|
|
433
|
+
* @param inheritedEventCount - exact fork-inherited prefix length for a seeded header.
|
|
399
434
|
* @returns a detached session.
|
|
400
435
|
*/
|
|
401
|
-
static create(
|
|
436
|
+
static create(
|
|
437
|
+
id: SessionId,
|
|
438
|
+
seed?: readonly SessionEvent[],
|
|
439
|
+
header?: SessionHeader,
|
|
440
|
+
inheritedEventCount?: SessionLogOffset,
|
|
441
|
+
): Session;
|
|
402
442
|
/**
|
|
403
443
|
* Restore a detached session by taking ownership of fresh persistence values.
|
|
404
444
|
* The storage format, event envelopes, sequence continuity, surface transitions,
|
|
@@ -406,18 +446,46 @@ declare class Session {
|
|
|
406
446
|
* @param id - restored session identity.
|
|
407
447
|
* @param seed - fresh detached events whose ownership is transferred.
|
|
408
448
|
* @param header - fresh detached metadata whose ownership is transferred.
|
|
449
|
+
* @param inheritedEventCount - exact fork-inherited prefix length decoded from storage.
|
|
409
450
|
* @returns a restored detached session.
|
|
410
451
|
*/
|
|
411
|
-
static fromRestore(
|
|
452
|
+
static fromRestore(
|
|
453
|
+
id: SessionId,
|
|
454
|
+
seed: readonly SessionEvent[],
|
|
455
|
+
header: SessionHeader,
|
|
456
|
+
inheritedEventCount: SessionLogOffset,
|
|
457
|
+
): Session;
|
|
458
|
+
/**
|
|
459
|
+
* Return the immutable event stored at one exact sequence number.
|
|
460
|
+
* @param seq - event sequence number.
|
|
461
|
+
* @returns the accepted event, or undefined when the log does not contain it.
|
|
462
|
+
*/
|
|
463
|
+
eventAt(seq: SessionSeq): SessionEvent | undefined;
|
|
464
|
+
/**
|
|
465
|
+
* Materialize an immutable snapshot of a half-open event sequence range.
|
|
466
|
+
* A full current snapshot is reused until the next append; every previously
|
|
467
|
+
* returned snapshot remains stable after later appends.
|
|
468
|
+
* @param fromSeq - non-negative inclusive sequence number; defaults to the log start.
|
|
469
|
+
* @param toSeqExclusive - non-negative exclusive sequence number; defaults to the current end.
|
|
470
|
+
* @returns a frozen array of the selected deeply frozen events.
|
|
471
|
+
*/
|
|
472
|
+
snapshotEvents(
|
|
473
|
+
fromSeq: SessionLogOffset = SessionLogOffset(0),
|
|
474
|
+
toSeqExclusive: SessionLogOffset = this.seq,
|
|
475
|
+
): readonly SessionEvent[];
|
|
476
|
+
/**
|
|
477
|
+
* Return this Session's events after its fork-inherited prefix.
|
|
478
|
+
* @returns a fresh array containing child-owned events in log order.
|
|
479
|
+
*/
|
|
480
|
+
ownEvents(): readonly SessionEvent[];
|
|
412
481
|
/**
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
* cast nor ordinary JavaScript can rewrite durable history.
|
|
482
|
+
* Whether one existing event position is outside the fork-inherited prefix.
|
|
483
|
+
* @param seq - event position in this Session.
|
|
484
|
+
* @returns true when the event belongs to this Session rather than its parent.
|
|
417
485
|
*/
|
|
418
|
-
|
|
486
|
+
isOwnSeq(seq: SessionSeq): boolean;
|
|
419
487
|
/** The next event's sequence number — always the log length (the `seq = log.length` contiguity contract). */
|
|
420
|
-
get seq():
|
|
488
|
+
get seq(): SessionLogOffset;
|
|
421
489
|
/**
|
|
422
490
|
* Append one typed event to the log and synchronously notify observers via
|
|
423
491
|
* the store-owned, module-private publication hooks. The hot path never blocks
|
|
@@ -435,7 +503,8 @@ declare class Session {
|
|
|
435
503
|
* declare how it joins the surface, the sole source of derived model
|
|
436
504
|
* history) and
|
|
437
505
|
* rejected by the compiler for non-surface types like `turn/start` or
|
|
438
|
-
* `assistant/
|
|
506
|
+
* `assistant/attempt`. Assistant messages embed their exact provider
|
|
507
|
+
* stream and cannot cite top-level source events.
|
|
439
508
|
* @returns the logged event — its assigned `seq`/`time` plus the SNAPSHOT of
|
|
440
509
|
* `data` that entered the log, so reading `event.data` back sees the logged
|
|
441
510
|
* value, never the caller's still-mutable input.
|
|
@@ -456,13 +525,13 @@ declare class Session {
|
|
|
456
525
|
append<T extends SessionEventType>(
|
|
457
526
|
type: T,
|
|
458
527
|
data: SessionEventMap[T],
|
|
459
|
-
...opts: T extends SurfaceEventType ? [opts: SurfaceIntent] : []
|
|
528
|
+
...opts: T extends SurfaceEventType ? [opts: SurfaceIntent<T>] : []
|
|
460
529
|
): SessionEvent<T>;
|
|
461
530
|
/**
|
|
462
531
|
* The {@link EpochHeader} in force after the log's last header event — the
|
|
463
532
|
* header the NEXT request will be compared against — or undefined before
|
|
464
533
|
* the first `request/header` snapshot. The live, incrementally-maintained
|
|
465
|
-
* form of `foldRequestHeader(session.
|
|
534
|
+
* form of `foldRequestHeader(session.snapshotEvents())`: each header event is folded
|
|
466
535
|
* once, when first seen, so a per-step read costs O(new events).
|
|
467
536
|
* @returns the folded header, or undefined when no header event exists yet.
|
|
468
537
|
*/
|
|
@@ -507,17 +576,17 @@ declare class Session {
|
|
|
507
576
|
`Session.deriveMessages()` projects the event log into the `Message[]` the model sees — cached (each surface node projected once, when first seen; a surface rewrite rebuilds) and frozen (a fresh array per call over shared, deep-frozen messages, so mutating logged history through a projection is unrepresentable). `deriveEventMessage(event)` is the per-node pure function the fold applies — public so external reconstructors and the dev invariant project a log prefix with exactly the same rules and cannot disagree with the cache. The projection rules:
|
|
508
577
|
|
|
509
578
|
- `user/message` → a user message carrying exact `content`; an optional envelope remains log-only display metadata.
|
|
510
|
-
- `assistant/message` → an assistant message with the provider and model that produced it plus optional adapter-private replay state.
|
|
579
|
+
- `assistant/message` → an assistant message with the provider and model that produced it plus optional adapter-private replay state. Its embedded compact stream is replay, usage, and UI evidence rather than a second message. An **empty-content** `assistant/message` is also skipped — a max-tokens step cut off with no content still records an `assistant/message` to hold its stream, usage, provider, and model, but a content-less assistant turn must not enter the provider transcript.
|
|
511
580
|
- `tool/result` → a user message carrying a `tool-result` block.
|
|
512
581
|
- `user/message` (injected context, i.e. non-`user` source) → a user-role message carrying its `content` verbatim at its chronological position; its typed source names the producer and carries any producer-specific data.
|
|
513
582
|
|
|
514
|
-
Everything else (`turn/*`, `step/*`, plugin-owned `llm/retry`) is structural and does not project into a message. Token accounting
|
|
583
|
+
Everything else (`turn/*`, `step/*`, `assistant/attempt`, plugin-owned `llm/retry`) is structural and does not project into a message. Token accounting expands the embedded stream on each `assistant/message` or `assistant/attempt`, while the message's top-level `usage` remains the committed-message authority when present. A failed model-request attempt therefore retains its provider usage without fabricating an assistant message. Current logical validation rejects request headers and assistant messages that omit provider/model instead of guessing a route; supported historical representations are normalized and validated by their adjacent format edge before a current Session exists.
|
|
515
584
|
|
|
516
585
|
## Live-session fork API
|
|
517
586
|
|
|
518
587
|
`ctx.sessions.create(id, { seed, meta })` is the low-level replay/fork primitive. For ordinary live-session forks, `SessionStore` exposes one policy API:
|
|
519
588
|
|
|
520
|
-
- `fork(source, boundary?, childSessionId?)` accepts a live `Session` object or live `SessionId`, selects source events through the inclusive `
|
|
589
|
+
- `fork(source, boundary?, childSessionId?)` accepts a live `Session` object or live `SessionId`, selects source events through the inclusive `SessionSeq` boundary (default: current last event), requires the selected prefix to end outside an open turn, then creates a live child session with deep-cloned seed events, `parentSession`, `isSeeded: true`, the exact `inheritedEventCount`, and inherited `cwd`.
|
|
521
590
|
|
|
522
591
|
An explicit `boundary` lets callers fork from any stable between-turn position, including a previous `turn/end` or a later standalone log-only event, even if the source has newer events or an open current turn. The API rejects a prefix that ends inside an open turn instead of clipping silently. Broader execution-relation sanity stays in the existing `dsh-invariants` plugin and persistence repair path rather than being duplicated in `fork()`. `dsh-subagent-fork-in-process` keeps its completed-prefix clipping because tool-time delegation usually starts while the parent turn is open; ordinary session branching should make the requested boundary explicit.
|
|
523
592
|
|
|
@@ -549,8 +618,10 @@ interface TurnEndReasonMap {
|
|
|
549
618
|
/** At least one step reached its output-token ceiling, even if a plugin continued the turn. */
|
|
550
619
|
'max-tokens': { kind: 'max-tokens' }
|
|
551
620
|
/**
|
|
552
|
-
* A
|
|
553
|
-
*
|
|
621
|
+
* A crash-orphaned turn was closed after the fact: agent-loop resume appends
|
|
622
|
+
* this closer for a stored log whose last turn never ended, and session-query
|
|
623
|
+
* synthesizes it on cold reads. The loop never emits this marker live, and
|
|
624
|
+
* the events recorded before the crash remain intact.
|
|
554
625
|
*/
|
|
555
626
|
interrupted: { kind: 'interrupted' }
|
|
556
627
|
}
|
|
@@ -566,9 +637,9 @@ The optional `dsh-session/invariant` companion enforces the relations owned by c
|
|
|
566
637
|
|
|
567
638
|
## The end-seed boundary: `session/end-seed`
|
|
568
639
|
|
|
569
|
-
A
|
|
640
|
+
A fresh fork constructor requires its seed to equal the inherited prefix and appends `session/end-seed { inherited: true }` at the exact durable cut. A restore retains that tagged marker and appends an ordinary `session/end-seed {}` only when its complete stored seed does not already end in a marker. Both forms are log-only and produce no message; `Session`'s constructor is the only legitimate writer.
|
|
570
641
|
|
|
571
|
-
|
|
642
|
+
For fork lineage, locate the LAST marker whose payload carries `inherited: true`; v2 decoding requires it exactly when `SessionHeader.isSeeded` is true and derives `inheritedEventCount` from its seq. For lifecycle ownership, locate the last `session/end-seed` of either form. Reopening a seed that already ends in any marker does not append another ordinary marker.
|
|
572
643
|
|
|
573
644
|
It exists because seed history and live work are otherwise byte-identical, which defeats any plugin owning a standalone open/close bracket: an unmatched `compaction/start` reads the same whether the writer crashed mid-compaction or is compacting right now. An opening marker before `session/end-seed` came from the constructor seed and belongs to an ended lifecycle, whatever ended it (a crash, a succeeding process, or a fork out of a still-running parent), so its owner may treat it as dead. That covers only brackets *this* session inherited: a concurrently live session holding an open bracket over the same history has its own boundary elsewhere, so tolerating concurrent writers needs a liveness signal beyond the log. Core writes the boundary and reads nothing from it — a bracket's vocabulary stays with its owning plugin, which is why crash repair closes turn/step/tool boundaries and never `compaction/*`.
|
|
574
645
|
|
|
@@ -584,7 +655,7 @@ The hook bridges' `hook/invoked` / `hook/result` pairs (from `@deepseek-ai/dsh-h
|
|
|
584
655
|
|
|
585
656
|
## Durability contract
|
|
586
657
|
|
|
587
|
-
What a persistence backend relies on: the durable log persists every event losslessly,
|
|
658
|
+
What a persistence backend relies on: the durable log persists every event losslessly, and every Assistant attempt is one `assistant/message` or `assistant/attempt` whose embedded compact stream preserves the original timed chunks. `seq` stays contiguous across these settlements and all interleaved events. A backend may choose its own storage framing for an event batch as long as a handle's `read()` returns the exact appended events; current JSONL v2 writes one row per event (see [persistence.md](persistence.md)). All `event.data` must be JSON-serializable; `Session.append` enforces this at the source (throwing on non-serializable data), so a bad event never enters the log and `session.snapshotEvents()` always equals what a backend can persist. Adding an event type that carries non-serializable data, corrupts core execution nesting, or violates its owner's declared relation is a breaking change to the on-disk format.
|
|
588
659
|
|
|
589
660
|
The backends that consume this contract are on [persistence.md](persistence.md).
|
|
590
661
|
|
|
@@ -622,7 +693,7 @@ resolveAgent(sessionId: SessionId): Promise<ApiSessionAgentResult>
|
|
|
622
693
|
* @param signal - optional caller cancellation for persistence reads.
|
|
623
694
|
* @returns the current attached state or persisted header and event prefix.
|
|
624
695
|
*/
|
|
625
|
-
inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<
|
|
696
|
+
inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<SessionInspection>
|
|
626
697
|
|
|
627
698
|
/**
|
|
628
699
|
* Read all visible Session rows without resuming an Agent.
|
|
@@ -730,7 +801,8 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<{ meta: SessionH
|
|
|
730
801
|
* Follow one Session log from its opening or resume cursor.
|
|
731
802
|
* @param request - durable address and last committed sequence already held by the caller.
|
|
732
803
|
* @param signal - cancellation owned by the Remote stream carrier.
|
|
733
|
-
* @returns a complete opening snapshot followed by gap-free event
|
|
804
|
+
* @returns a complete opening snapshot followed by gap-free durable event
|
|
805
|
+
* frames and optional cursorless assistant-stream frames.
|
|
734
806
|
*/
|
|
735
807
|
@Remote({ mode: 'stream' }) follow(request: SessionFollowRequest, signal: AbortSignal): AsyncIterable<SessionFollowFrame>
|
|
736
808
|
|
|
@@ -742,7 +814,7 @@ inspect( sessionId: SessionId, signal?: AbortSignal, ): Promise<{ meta: SessionH
|
|
|
742
814
|
@Remote({ mode: 'stream' }) control(signal: AbortSignal): AsyncIterable<SessionControlFrame>
|
|
743
815
|
```
|
|
744
816
|
|
|
745
|
-
Types: [
|
|
817
|
+
Types: [SessionId](core.md) · [SessionInspection](persistence.md) · [SessionSearchRequest](session-query.md)
|
|
746
818
|
|
|
747
819
|
Source: [`packages/api/session-controller/src/index.ts`](../../packages/api/session-controller/src/index.ts)
|
|
748
820
|
|
|
@@ -752,7 +824,7 @@ Source: [`packages/api/session-controller/src/index.ts`](../../packages/api/sess
|
|
|
752
824
|
|
|
753
825
|
In-memory session store (`ctx.sessions`).
|
|
754
826
|
|
|
755
|
-
Persistence is intentionally not implemented here —
|
|
827
|
+
Persistence is intentionally not implemented here — the agent lifecycle attaches a session-log writer to each published session's write handle; a session published outside that lifecycle persists nothing.
|
|
756
828
|
|
|
757
829
|
```ts cordis-catalog
|
|
758
830
|
/**
|
|
@@ -875,7 +947,7 @@ list(): Session[]
|
|
|
875
947
|
* `SessionStore`'s id policy.
|
|
876
948
|
* @returns The created live child session.
|
|
877
949
|
*/
|
|
878
|
-
fork(source: SessionForkSource, boundary?:
|
|
950
|
+
fork(source: SessionForkSource, boundary?: SessionSeq, childSessionId?: SessionId): Session
|
|
879
951
|
```
|
|
880
952
|
|
|
881
953
|
Types: [CreateSessionOptions](persistence.md) · [PrepareSessionOptions](persistence.md) · [SessionId](core.md)
|