dsh-context 0.35.0 → 0.37.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/README.md +8 -0
- package/lib/client.js +256 -64
- package/lib/index.d.ts +98 -317
- package/lib/index.js +261 -6
- package/package.json +8 -9
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { Context
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import "@deepseek-ai/dsh-session";
|
|
3
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
4
4
|
//#region src/host/config.d.ts
|
|
5
5
|
interface Config {
|
|
6
6
|
/** Cap on kept per-step request records (the hard step backstop). */
|
|
@@ -29,13 +29,90 @@ declare const Config: z.ZodPreprocess<z.ZodObject<{
|
|
|
29
29
|
maxArchiveNodes: z.ZodDefault<z.ZodNumber>;
|
|
30
30
|
}, z.core.$strict>>;
|
|
31
31
|
//#endregion
|
|
32
|
-
//#region src/
|
|
32
|
+
//#region src/host/headers.d.ts
|
|
33
|
+
interface HeadersState {
|
|
34
|
+
headers: HeaderRecord[];
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/host/fold.d.ts
|
|
33
38
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
39
|
+
* History retention bounds (configurable since 0.11 — see config.ts; these
|
|
40
|
+
* are the defaults' values). The fold keeps per-STEP request records; once the
|
|
41
|
+
* newest run count exceeds `maxKeptTurns`, the timeline is trimmed to the
|
|
42
|
+
* most recent whole TURN runs (never cutting a turn in half), so turn
|
|
43
|
+
* granularity can always show the full recent turn range instead of a
|
|
44
|
+
* step-count fragment. The turn-run trim runs whenever the cap is crossed
|
|
45
|
+
* (not only when the raw step bound is), so the bounded state stays at the
|
|
46
|
+
* newest ~`maxKeptTurns` turns deterministically as a live log grows.
|
|
38
47
|
*/
|
|
48
|
+
interface TimelineState {
|
|
49
|
+
/** Model-visible surface, newest last. */
|
|
50
|
+
surface: SurfaceNode[];
|
|
51
|
+
sums: Record<Category, number>;
|
|
52
|
+
systemTokens: number;
|
|
53
|
+
toolsTokens: number;
|
|
54
|
+
/**
|
|
55
|
+
* The projection-cache precondition is plain JSON: a property whose value
|
|
56
|
+
* is `undefined` makes the whole checkpoint unserializable
|
|
57
|
+
* (`snapshotJsonValue` rejects it), which fails EVERY cache write for the
|
|
58
|
+
* session — including the `title` projection row that powers the session
|
|
59
|
+
* list after a restart. Optional fields therefore use absent properties
|
|
60
|
+
* (`model`/`provider`/`lastModel`/`contextWindow` are simply not set until
|
|
61
|
+
* a value is known) instead of `undefined`-valued ones. Reads via
|
|
62
|
+
* `state.model` are identical for both shapes (`undefined` on miss).
|
|
63
|
+
*/
|
|
64
|
+
model?: string;
|
|
65
|
+
provider?: string;
|
|
66
|
+
lastModel?: string;
|
|
67
|
+
contextWindow?: number;
|
|
68
|
+
requests: RequestRecord[];
|
|
69
|
+
events: ContextEventRecord[];
|
|
70
|
+
/**
|
|
71
|
+
* Recently removed surface nodes (stamped COPIES carrying `gone`), in
|
|
72
|
+
* removal order. Feeds the Context browser's per-step reconstruction.
|
|
73
|
+
* Bounded two ways in trimState: capped to `maxArchiveNodes`, and pruned
|
|
74
|
+
* to removals after the oldest retained request (older removals can only
|
|
75
|
+
* serve steps the requests trim already forgot).
|
|
76
|
+
*/
|
|
77
|
+
archived: SurfaceNode[];
|
|
78
|
+
/**
|
|
79
|
+
* Session-cost raw material: cumulative billed-token totals per DeepSeek
|
|
80
|
+
* V4 model family and pricing period (see SessionCostUsage). Running
|
|
81
|
+
* totals — never trimmed, so the estimate always covers the COMPLETE
|
|
82
|
+
* session log even after the request/event retention bounds cut in.
|
|
83
|
+
* Absent until a v4-flash / v4-pro request reports usage.
|
|
84
|
+
*/
|
|
85
|
+
cost?: SessionCostUsage;
|
|
86
|
+
archiveFloor?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Tool callId → name, armed by `tool/call` and DELETED when its
|
|
89
|
+
* `tool/result` folds in (one result per call, in log order) — the map
|
|
90
|
+
* stays at pending-call size instead of growing for the session's whole
|
|
91
|
+
* lifetime (it is persisted state, shallow-copied by every fold step).
|
|
92
|
+
*/
|
|
93
|
+
callNames: Record<string, string>;
|
|
94
|
+
/**
|
|
95
|
+
* Seq list of the surface nodes the next replacement will shadow, armed by
|
|
96
|
+
* the metering event (`compaction/summary` | `compaction/prune`) and
|
|
97
|
+
* consumed by the replacement that must follow it synchronously. The
|
|
98
|
+
* producer's shadow price covers exactly these seqs — which can differ
|
|
99
|
+
* from the replacement's declared range (pruned replacement nodes keep
|
|
100
|
+
* their own seqs, beyond the range end) — so removal must follow the seqs.
|
|
101
|
+
* Absent until armed, and REMOVED (not set to `undefined`) when consumed,
|
|
102
|
+
* to keep the state plain JSON for the projection cache.
|
|
103
|
+
*/
|
|
104
|
+
pendingShadowedSeqs?: number[];
|
|
105
|
+
/**
|
|
106
|
+
* The seq of the compaction/prune event that armed `pendingShadowedSeqs` —
|
|
107
|
+
* the shadowed path rewrites that event's `tokens` from the gross shadow
|
|
108
|
+
* price to the NET freed amount (removed nodes minus the synchronous
|
|
109
|
+
* replacement), so the row matches the drop the trend chart shows. Same
|
|
110
|
+
* arm/remove lifecycle as `pendingShadowedSeqs`.
|
|
111
|
+
*/
|
|
112
|
+
pendingShadowEventSeq?: number;
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/shared/types.d.ts
|
|
39
116
|
declare module '@deepseek-ai/dsh-session-projection/types' {
|
|
40
117
|
interface SessionProjectionMap {
|
|
41
118
|
/**
|
|
@@ -55,6 +132,10 @@ declare module '@deepseek-ai/dsh-session-projection/types' {
|
|
|
55
132
|
*/
|
|
56
133
|
contextHeaders: ContextHeaders;
|
|
57
134
|
}
|
|
135
|
+
interface SessionProjectionStateMap {
|
|
136
|
+
contextTimeline: TimelineState;
|
|
137
|
+
contextHeaders: HeadersState;
|
|
138
|
+
}
|
|
58
139
|
}
|
|
59
140
|
type Category = 'user' | 'inject' | 'assistant' | 'tool';
|
|
60
141
|
interface Snapshot {
|
|
@@ -247,6 +328,15 @@ interface HeaderTool {
|
|
|
247
328
|
tokens: number;
|
|
248
329
|
/** Producer-declared description (may be long; the browser truncates). */
|
|
249
330
|
description?: string;
|
|
331
|
+
/**
|
|
332
|
+
* The registering plugin's label, when attribution is known: either a
|
|
333
|
+
* `plugin` field carried by the raw header entry (harness-provided) or the
|
|
334
|
+
* host's best-effort attribution (`mcp:<server>` for MCP tools, or the
|
|
335
|
+
* pinned first-party package map). `UNKNOWN_TOOL_SOURCE` marks a tool whose
|
|
336
|
+
* provider predates the attribution hook; absent means nothing is known and
|
|
337
|
+
* the browser shows no tag.
|
|
338
|
+
*/
|
|
339
|
+
plugin?: string;
|
|
250
340
|
/** The raw JSON schema object the model received (plain JSON). */
|
|
251
341
|
schema?: unknown;
|
|
252
342
|
}
|
|
@@ -264,315 +354,6 @@ interface ContextHeaders {
|
|
|
264
354
|
headers: HeaderRecord[];
|
|
265
355
|
}
|
|
266
356
|
//#endregion
|
|
267
|
-
//#region src/host/fold.d.ts
|
|
268
|
-
/**
|
|
269
|
-
* History retention bounds (configurable since 0.11 — see config.ts; these
|
|
270
|
-
* are the defaults' values). The fold keeps per-STEP request records; once the
|
|
271
|
-
* newest run count exceeds `maxKeptTurns`, the timeline is trimmed to the
|
|
272
|
-
* most recent whole TURN runs (never cutting a turn in half), so turn
|
|
273
|
-
* granularity can always show the full recent turn range instead of a
|
|
274
|
-
* step-count fragment. The turn-run trim runs whenever the cap is crossed
|
|
275
|
-
* (not only when the raw step bound is), so the bounded state stays at the
|
|
276
|
-
* newest ~`maxKeptTurns` turns deterministically as a live log grows.
|
|
277
|
-
*/
|
|
278
|
-
interface TimelineState {
|
|
279
|
-
/** Model-visible surface, newest last. */
|
|
280
|
-
surface: SurfaceNode[];
|
|
281
|
-
sums: Record<Category, number>;
|
|
282
|
-
systemTokens: number;
|
|
283
|
-
toolsTokens: number;
|
|
284
|
-
/**
|
|
285
|
-
* The projection-cache precondition is plain JSON: a property whose value
|
|
286
|
-
* is `undefined` makes the whole checkpoint unserializable
|
|
287
|
-
* (`snapshotJsonValue` rejects it), which fails EVERY cache write for the
|
|
288
|
-
* session — including the `title` projection row that powers the session
|
|
289
|
-
* list after a restart. Optional fields therefore use absent properties
|
|
290
|
-
* (`model`/`provider`/`lastModel`/`contextWindow` are simply not set until
|
|
291
|
-
* a value is known) instead of `undefined`-valued ones. Reads via
|
|
292
|
-
* `state.model` are identical for both shapes (`undefined` on miss).
|
|
293
|
-
*/
|
|
294
|
-
model?: string;
|
|
295
|
-
provider?: string;
|
|
296
|
-
lastModel?: string;
|
|
297
|
-
contextWindow?: number;
|
|
298
|
-
requests: RequestRecord[];
|
|
299
|
-
events: ContextEventRecord[];
|
|
300
|
-
/**
|
|
301
|
-
* Recently removed surface nodes (stamped COPIES carrying `gone`), in
|
|
302
|
-
* removal order. Feeds the Context browser's per-step reconstruction.
|
|
303
|
-
* Bounded two ways in trimState: capped to `maxArchiveNodes`, and pruned
|
|
304
|
-
* to removals after the oldest retained request (older removals can only
|
|
305
|
-
* serve steps the requests trim already forgot).
|
|
306
|
-
*/
|
|
307
|
-
archived: SurfaceNode[];
|
|
308
|
-
/**
|
|
309
|
-
* Session-cost raw material: cumulative billed-token totals per DeepSeek
|
|
310
|
-
* V4 model family and pricing period (see SessionCostUsage). Running
|
|
311
|
-
* totals — never trimmed, so the estimate always covers the COMPLETE
|
|
312
|
-
* session log even after the request/event retention bounds cut in.
|
|
313
|
-
* Absent until a v4-flash / v4-pro request reports usage.
|
|
314
|
-
*/
|
|
315
|
-
cost?: SessionCostUsage;
|
|
316
|
-
archiveFloor?: number;
|
|
317
|
-
/**
|
|
318
|
-
* Tool callId → name, armed by `tool/call` and DELETED when its
|
|
319
|
-
* `tool/result` folds in (one result per call, in log order) — the map
|
|
320
|
-
* stays at pending-call size instead of growing for the session's whole
|
|
321
|
-
* lifetime (it is persisted state, shallow-copied by every fold step).
|
|
322
|
-
*/
|
|
323
|
-
callNames: Record<string, string>;
|
|
324
|
-
/**
|
|
325
|
-
* Seq list of the surface nodes the next replacement will shadow, armed by
|
|
326
|
-
* the metering event (`compaction/summary` | `compaction/prune`) and
|
|
327
|
-
* consumed by the replacement that must follow it synchronously. The
|
|
328
|
-
* producer's shadow price covers exactly these seqs — which can differ
|
|
329
|
-
* from the replacement's declared range (pruned replacement nodes keep
|
|
330
|
-
* their own seqs, beyond the range end) — so removal must follow the seqs.
|
|
331
|
-
* Absent until armed, and REMOVED (not set to `undefined`) when consumed,
|
|
332
|
-
* to keep the state plain JSON for the projection cache.
|
|
333
|
-
*/
|
|
334
|
-
pendingShadowedSeqs?: number[];
|
|
335
|
-
/**
|
|
336
|
-
* The seq of the compaction/prune event that armed `pendingShadowedSeqs` —
|
|
337
|
-
* the shadowed path rewrites that event's `tokens` from the gross shadow
|
|
338
|
-
* price to the NET freed amount (removed nodes minus the synchronous
|
|
339
|
-
* replacement), so the row matches the drop the trend chart shows. Same
|
|
340
|
-
* arm/remove lifecycle as `pendingShadowedSeqs`.
|
|
341
|
-
*/
|
|
342
|
-
pendingShadowEventSeq?: number;
|
|
343
|
-
}
|
|
344
|
-
//#endregion
|
|
345
|
-
//#region node_modules/.pnpm/@deepseek-ai+dsh-session-projection@0.1.0-rc.8_@deepseek-ai+cordis@4.0.1_@deepseek-ai+d_c0ffab70d18276fadfe75ed916313ea3/node_modules/@deepseek-ai/dsh-session-projection/lib/types/types.d.ts
|
|
346
|
-
/**
|
|
347
|
-
* Pure-type outlet of the session-projection Service Definition: the one projection type
|
|
348
|
-
* table, importable from client aggregates without dragging the host-side
|
|
349
|
-
* cordis Context merges of the package root (dsh-agent → dsh-session). Domain
|
|
350
|
-
* packages may declare-merge through either the package root or this outlet —
|
|
351
|
-
* re-export preserves symbol identity, so both land on the same table.
|
|
352
|
-
*
|
|
353
|
-
* @module @deepseek-ai/dsh-session-projection/types
|
|
354
|
-
*/
|
|
355
|
-
/**
|
|
356
|
-
* The single projection type table for the whole chain (host provider, wire
|
|
357
|
-
* block, client cell, React hook). Domain packages merge their key here via
|
|
358
|
-
* declaration merging; values are wire-JSON whole values. How a value is
|
|
359
|
-
* rendered is the slot system's business, never this layer's.
|
|
360
|
-
*/
|
|
361
|
-
interface SessionProjectionMap {}
|
|
362
|
-
//#endregion
|
|
363
|
-
//#region node_modules/.pnpm/@deepseek-ai+dsh-session-projection@0.1.0-rc.8_@deepseek-ai+cordis@4.0.1_@deepseek-ai+d_c0ffab70d18276fadfe75ed916313ea3/node_modules/@deepseek-ai/dsh-session-projection/lib/types/index.d.ts
|
|
364
|
-
declare module '@deepseek-ai/cordis' {
|
|
365
|
-
interface Context {
|
|
366
|
-
sessionProjections: SessionProjectionRegistry;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* One domain's state-driven computation unit: three pure synchronous
|
|
371
|
-
* functions plus declarations — never an opaque getter. The framework drives
|
|
372
|
-
* `apply` on every committed session event; the domain holds no
|
|
373
|
-
* subscriptions and owns only the mathematics. All three functions MUST be
|
|
374
|
-
* synchronous (an async unit would tear the carriers' consistency cut) and
|
|
375
|
-
* `state` MUST be plain JSON (the persisted-cache precondition).
|
|
376
|
-
*/
|
|
377
|
-
interface ProjectionDefinition<K extends keyof SessionProjectionMap, S> {
|
|
378
|
-
/** The projection key this unit owns (its `SessionProjectionMap` entry). */
|
|
379
|
-
key: K;
|
|
380
|
-
/** Validates the wire payload (`view` output) before it leaves the host. */
|
|
381
|
-
schema: ZodType<SessionProjectionMap[K]>;
|
|
382
|
-
/**
|
|
383
|
-
* State for the empty log.
|
|
384
|
-
* @returns the initial state.
|
|
385
|
-
*/
|
|
386
|
-
init(): S;
|
|
387
|
-
/**
|
|
388
|
-
* Pure transition: previous state + one committed event → next state. A
|
|
389
|
-
* unit uninterested in an event MUST return the same state reference — an
|
|
390
|
-
* unchanged reference (`Object.is`) produces zero downstream work.
|
|
391
|
-
* @param state - the state covering all prior events.
|
|
392
|
-
* @param event - the next committed session event.
|
|
393
|
-
* @returns the next state (same reference when the event is not the unit's).
|
|
394
|
-
*/
|
|
395
|
-
apply(state: S, event: SessionEvent): S;
|
|
396
|
-
/**
|
|
397
|
-
* State → wire payload (the read-side projection).
|
|
398
|
-
* @param state - the current state.
|
|
399
|
-
* @returns the whole current value for this unit's key.
|
|
400
|
-
*/
|
|
401
|
-
view(state: S): SessionProjectionMap[K];
|
|
402
|
-
/**
|
|
403
|
-
* Persisted-cache invalidation version: bump whenever the serialized state fields or the
|
|
404
|
-
* fold semantics change, so persisted `(sessionId, key, ver, seq, val)`
|
|
405
|
-
* rows from an older unit are discarded instead of being forward-applied
|
|
406
|
-
* into garbage. Non-negative integer.
|
|
407
|
-
*/
|
|
408
|
-
stateVersion: number;
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Change-feed listener: one unit's value changed for one session. `value` is
|
|
412
|
-
* the schema-validated `view` output; `seq` is the unit's watermark at
|
|
413
|
-
* emission (the seq of the event that caused the change).
|
|
414
|
-
*/
|
|
415
|
-
type ProjectionChangeListener = (session: Session, key: Extract<keyof SessionProjectionMap, string>, value: unknown, seq: number) => void;
|
|
416
|
-
/**
|
|
417
|
-
* One consistent read cut over every registered unit for one session.
|
|
418
|
-
* `asOfSeq` is the shared watermark — the seq of the last event every value
|
|
419
|
-
* reflects (`-1` for an empty log, mirroring `session/subscribed.lastSeq`).
|
|
420
|
-
*/
|
|
421
|
-
interface ProjectionSnapshot {
|
|
422
|
-
/** Seq of the last event the values reflect; -1 for an empty log. */
|
|
423
|
-
asOfSeq: number;
|
|
424
|
-
/** Whole current value per registered key. */
|
|
425
|
-
values: Partial<SessionProjectionMap>;
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* One unit's checkpoint: its internal state (plain JSON by the unit
|
|
429
|
-
* contract), the seq of the last event folded into it, and the unit
|
|
430
|
-
* `stateVersion` that produced it — the persisted projection-cache row
|
|
431
|
-
* `(sessionId, key, ver, seq, val)` minus the two outer keys. A row is
|
|
432
|
-
* never authoritative, only a fold shortcut: `restore` discards it on a
|
|
433
|
-
* version mismatch or when it claims events past the stored log end.
|
|
434
|
-
*/
|
|
435
|
-
interface ProjectionCheckpointRow {
|
|
436
|
-
/** The registering unit's `stateVersion` at fold time. */
|
|
437
|
-
ver: number;
|
|
438
|
-
/** Seq of the last event folded into `val`; -1 for the empty log. */
|
|
439
|
-
seq: number;
|
|
440
|
-
/** The unit's internal state — plain JSON per the unit contract. */
|
|
441
|
-
val: unknown;
|
|
442
|
-
}
|
|
443
|
-
/** Checkpoint rows keyed by projection key (one session's persisted cache value). */
|
|
444
|
-
type ProjectionCheckpoint = Record<string, ProjectionCheckpointRow>;
|
|
445
|
-
/**
|
|
446
|
-
* `ctx.sessionProjections`: the projection unit table and its drive. The
|
|
447
|
-
* service subscribes to `session/event` once; every committed event passes
|
|
448
|
-
* every registered unit's `apply` (eager drive), and a changed state
|
|
449
|
-
* reference notifies the change feed with the schema-validated view.
|
|
450
|
-
* Cells build lazily — a unit registered after events flowed, or a session
|
|
451
|
-
* older than the registry, folds `init` over the in-memory log on first
|
|
452
|
-
* touch (event or read). Registration is an effect (disposer rides the
|
|
453
|
-
* calling fiber): an unloaded domain plugin's key disappears from snapshots
|
|
454
|
-
* and clients read it as capability absence. Domain
|
|
455
|
-
* plugins register under `ctx.inject(['sessionProjections'], …)` so headless
|
|
456
|
-
* assemblies without the registry stay unaffected. Registrants sharing a key
|
|
457
|
-
* share one unit and are counted: the same tool package mounted in N agent
|
|
458
|
-
* presets registers N times, and the key survives until the last one
|
|
459
|
-
* unloads.
|
|
460
|
-
*/
|
|
461
|
-
declare class SessionProjectionRegistry extends Service {
|
|
462
|
-
private readonly registrations;
|
|
463
|
-
private readonly listeners;
|
|
464
|
-
/**
|
|
465
|
-
* Create and install the registry as `ctx.sessionProjections`.
|
|
466
|
-
* @param ctx - Cordis context that owns the service.
|
|
467
|
-
*/
|
|
468
|
-
constructor(ctx: Context);
|
|
469
|
-
/**
|
|
470
|
-
* Register one domain's unit. The registration is an effect on the calling
|
|
471
|
-
* context's fiber: disposing the fiber (or calling the returned disposer)
|
|
472
|
-
* removes the key — and the unit's cached cells — from subsequent drives
|
|
473
|
-
* and snapshots.
|
|
474
|
-
* @param definition - key, state schema, pure unit functions, and stateVersion.
|
|
475
|
-
* @returns the exact disposer that unregisters this unit.
|
|
476
|
-
*/
|
|
477
|
-
register<K extends keyof SessionProjectionMap, S>(definition: ProjectionDefinition<K, S>): () => void;
|
|
478
|
-
/**
|
|
479
|
-
* Subscribe to the change feed. The registration is an effect on the
|
|
480
|
-
* calling context's fiber.
|
|
481
|
-
* @param listener - called once per unit whose state reference changed, per committed event.
|
|
482
|
-
* @returns the exact disposer that unsubscribes.
|
|
483
|
-
*/
|
|
484
|
-
onChanged(listener: ProjectionChangeListener): () => void;
|
|
485
|
-
/**
|
|
486
|
-
* One consistent cut over every registered unit for one session, read from
|
|
487
|
-
* the watermark cache (missing cells fold lazily over the in-memory log).
|
|
488
|
-
* Fully synchronous — every value and `asOfSeq` reflect the same log
|
|
489
|
-
* position. Each value passes its unit's schema before leaving.
|
|
490
|
-
* @param session - the session whose projection values are read.
|
|
491
|
-
* @returns the snapshot; `values` is empty when no unit is registered.
|
|
492
|
-
*/
|
|
493
|
-
snapshot(session: Session): ProjectionSnapshot;
|
|
494
|
-
/**
|
|
495
|
-
* State-level checkpoint of every registered unit for one session, read
|
|
496
|
-
* from the watermark cache (missing cells fold lazily over the in-memory
|
|
497
|
-
* log). This is the write side of the persisted projection cache: the
|
|
498
|
-
* returned rows are the `(key → {ver, seq, val})` part of the durable
|
|
499
|
-
* `(sessionId, key, ver, seq, val)`
|
|
500
|
-
* rows. Every `val` is a DETACHED structured clone — never the live
|
|
501
|
-
* cell reference: the watermark cache is this registry's authoritative
|
|
502
|
-
* mutable state, and a caller reaching the live reference could corrupt
|
|
503
|
-
* every subsequent snapshot and frame through it (plain JSON by the unit
|
|
504
|
-
* contract, so the clone is total).
|
|
505
|
-
* @param session - the session whose unit states are checkpointed.
|
|
506
|
-
* @returns one row per registered key; empty when no unit is registered.
|
|
507
|
-
*/
|
|
508
|
-
checkpoint(session: Session): ProjectionCheckpoint;
|
|
509
|
-
/**
|
|
510
|
-
* The stored seq a {@link restore} tail read over `checkpoint` must start
|
|
511
|
-
* at: one event BELOW the lowest usable watermark (a row is usable when
|
|
512
|
-
* its `ver` matches the live unit's `stateVersion`; an absent or mismatched row
|
|
513
|
-
* pulls the floor to `0` — that key must refold the full log). The
|
|
514
|
-
* one-below anchor is load-bearing: the tail then proves how far the
|
|
515
|
-
* stored log still extends, so {@link restore} can detect a log that
|
|
516
|
-
* shrank below a row's watermark (crash-repair truncation) instead of
|
|
517
|
-
* serving the stale row as current — an empty tail read from the anchor
|
|
518
|
-
* yields an end below every watermark and the restore rejects for a full
|
|
519
|
-
* re-read.
|
|
520
|
-
* @param checkpoint - persisted rows for one session (possibly stale or empty).
|
|
521
|
-
* @returns the seq to hand the persistence `readFrom`, or `undefined`
|
|
522
|
-
* when no unit is registered (no read needed — {@link restore} would
|
|
523
|
-
* serve empty values regardless).
|
|
524
|
-
*/
|
|
525
|
-
restoreFloor(checkpoint: ProjectionCheckpoint): number | undefined;
|
|
526
|
-
/**
|
|
527
|
-
* View a checkpoint's rows without any log read: for every registered
|
|
528
|
-
* unit whose row's `ver` matches, serve the schema-validated
|
|
529
|
-
* `view` of the stored state; mismatched or absent rows leave their key
|
|
530
|
-
* absent (a cold or listing consumer treats it as not-yet-available and a
|
|
531
|
-
* fuller read path refolds it). The zero-I/O rung of the read ladder —
|
|
532
|
-
* values are as stale as their rows, never wrong.
|
|
533
|
-
* @param checkpoint - persisted rows for one session (possibly stale or empty).
|
|
534
|
-
* @returns whole values per key with a usable row; empty when none.
|
|
535
|
-
*/
|
|
536
|
-
viewCheckpoint(checkpoint: ProjectionCheckpoint): Partial<SessionProjectionMap>;
|
|
537
|
-
/**
|
|
538
|
-
* Cold read: fold every registered unit over a stored log suffix, seeding
|
|
539
|
-
* each from its checkpoint row when usable — the one read recipe (cached
|
|
540
|
-
* state + forward tail replay + `view`) applied without a live `Session`.
|
|
541
|
-
* Call with the events returned by a persistence
|
|
542
|
-
* `readFrom(id, restoreFloor(checkpoint))` and that same floor as
|
|
543
|
-
* `baseSeq`; the floor's one-below anchor makes the supplied end honest,
|
|
544
|
-
* so a shrunk log is detected here. A row is usable iff its
|
|
545
|
-
* `ver` matches the live unit's `stateVersion`, it does not predate `baseSeq`
|
|
546
|
-
* (`seq >= baseSeq - 1`), and it does not claim events past the
|
|
547
|
-
* supplied end (`seq <= endSeq`); an unusable row is discarded
|
|
548
|
-
* and its key refolds from `init` — which is only sound over the full
|
|
549
|
-
* log, so a discarded row with `baseSeq > 0` throws (the caller re-reads
|
|
550
|
-
* from seq 0, e.g. after a crash-repair truncation shrank the log below
|
|
551
|
-
* a row's watermark).
|
|
552
|
-
* @param checkpoint - persisted rows for one session (possibly stale or empty).
|
|
553
|
-
* @param events - the stored events with `seq >= baseSeq`, in seq order.
|
|
554
|
-
* @param baseSeq - the seq `events` starts at (its first event's seq when non-empty).
|
|
555
|
-
* @returns the snapshot cut at the supplied log end (`asOfSeq` is the last
|
|
556
|
-
* supplied event's seq, `baseSeq - 1` for an empty tail) plus the
|
|
557
|
-
* refreshed checkpoint rows at that cut, ready for a durable write-back.
|
|
558
|
-
*/
|
|
559
|
-
restore(checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: number): {
|
|
560
|
-
snapshot: ProjectionSnapshot;
|
|
561
|
-
checkpoint: ProjectionCheckpoint;
|
|
562
|
-
};
|
|
563
|
-
/** Fold one unit from init over `events`, producing a cell watermarked at the last folded event. */
|
|
564
|
-
private buildCell;
|
|
565
|
-
/** Read (or lazily build, folding the full in-memory log) one unit's cell. */
|
|
566
|
-
private cellFor;
|
|
567
|
-
/** Eager drive: pass one committed event through every registered unit; notify on changed references. */
|
|
568
|
-
private drive;
|
|
569
|
-
}
|
|
570
|
-
//#endregion
|
|
571
|
-
//#region src/host/headers.d.ts
|
|
572
|
-
interface HeadersState {
|
|
573
|
-
headers: HeaderRecord[];
|
|
574
|
-
}
|
|
575
|
-
//#endregion
|
|
576
357
|
//#region src/host/index.d.ts
|
|
577
358
|
declare const name = "dsh-context";
|
|
578
359
|
declare const inject: string[];
|