dsh-context 0.55.0 → 0.56.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 +10 -1
- package/lib/client.js +435 -353
- package/lib/index.d.ts +43 -56
- package/lib/index.js +54 -124
- package/package.json +27 -13
package/lib/index.d.ts
CHANGED
|
@@ -35,17 +35,6 @@ interface HeadersState {
|
|
|
35
35
|
headers: StoredHeaderRecord[];
|
|
36
36
|
}
|
|
37
37
|
//#endregion
|
|
38
|
-
//#region src/host/logShapes.d.ts
|
|
39
|
-
/**
|
|
40
|
-
* The decode bucket a stream's `block-start.blockType` names: the model's
|
|
41
|
-
* thinking, the answer text, or the tool-call arguments. Undefined for an
|
|
42
|
-
* unknown/hostile marker, whose interval then stays unattributed rather than
|
|
43
|
-
* poisoning a bucket.
|
|
44
|
-
*/
|
|
45
|
-
type DecodeKind = 'reasoning' | 'text' | 'toolarg';
|
|
46
|
-
/** Per-kind count of opened decode blocks (see {@link decodeTallyOfStream}). */
|
|
47
|
-
type DecodeCounts = Record<DecodeKind, number>;
|
|
48
|
-
//#endregion
|
|
49
38
|
//#region src/host/fold.d.ts
|
|
50
39
|
/**
|
|
51
40
|
* History retention bounds (configurable since 0.11 — see config.ts; these
|
|
@@ -63,9 +52,8 @@ interface TimelineState {
|
|
|
63
52
|
sums: Record<Category, number>;
|
|
64
53
|
systemTokens: number;
|
|
65
54
|
/**
|
|
66
|
-
* The live system-prompt nodes, oldest first — a
|
|
67
|
-
* surface nodes
|
|
68
|
-
* envelope defines. `systemTokens` is the LAST entry with tokens > 0 (the
|
|
55
|
+
* The live system-prompt nodes, oldest first — a log's `system/message`
|
|
56
|
+
* surface nodes. `systemTokens` is the LAST entry with tokens > 0 (the
|
|
69
57
|
* harness's own "last nonempty surviving system" rule), so an empty dormant
|
|
70
58
|
* node keeps its position without clearing the prompt. Bounded by
|
|
71
59
|
* SYSTEM_NODES_MAX. ABSENT on rows folded before this field existed — the
|
|
@@ -73,16 +61,6 @@ interface TimelineState {
|
|
|
73
61
|
* epoch's own envelope figure.
|
|
74
62
|
*/
|
|
75
63
|
systems?: SystemPromptNode[];
|
|
76
|
-
/**
|
|
77
|
-
* Whether `systems` was built from the V0/V2 request ENVELOPE
|
|
78
|
-
* (`header.system`) rather than from V3 `system/message` events. Only then
|
|
79
|
-
* may a system-less header CLEAR the list: its canonical V0 meaning is
|
|
80
|
-
* "this request has no system prompt", while a V3 header never carries one
|
|
81
|
-
* (its prompt lives in the message history). Absent = log-sourced, and
|
|
82
|
-
* never materialized as an `undefined`-valued property (plain-JSON
|
|
83
|
-
* precondition — see the note above `model`).
|
|
84
|
-
*/
|
|
85
|
-
systemsFromHeader?: true;
|
|
86
64
|
toolsTokens: number;
|
|
87
65
|
/**
|
|
88
66
|
* The projection-cache precondition is plain JSON: a property whose value
|
|
@@ -162,31 +140,16 @@ interface TimelineState {
|
|
|
162
140
|
/**
|
|
163
141
|
* The open step's start instant, armed by `step/start` and consumed by the
|
|
164
142
|
* `assistant/message` (TTFT/generation split) and `step/end` (wall time)
|
|
165
|
-
* that follow it;
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* `pendingShadowedSeqs`.
|
|
172
|
-
*
|
|
173
|
-
* `decode`, `blocks` and `block` carry the generation split (reasoning /
|
|
174
|
-
* answer text / tool arguments — see TimingTotals): a V0 log's
|
|
175
|
-
* `assistant/chunk` `block-start` markers open `block`, close the previous
|
|
176
|
-
* one into `decode`, and count the opened bucket into `blocks` (the card's
|
|
177
|
-
* per-slice tally); a V2+ log carries no such events, so `decode` stays
|
|
178
|
-
* absent and `assistant/message` reads the spans and counts off its embedded
|
|
179
|
-
* stream instead.
|
|
143
|
+
* that follow it; the message's embedded stream stamps `firstToken` —
|
|
144
|
+
* absent when the stream carried none (an aborted step), which leaves that
|
|
145
|
+
* call's model time unattributed. One slot, not a map: steps are sequential
|
|
146
|
+
* in the log, so the newest `step/start` is the one those events close — a
|
|
147
|
+
* hostile interleaved log degrades to skipped durations, never to
|
|
148
|
+
* unbounded state. Same arm/remove lifecycle as `pendingShadowedSeqs`.
|
|
180
149
|
*/
|
|
181
150
|
stepStart?: {
|
|
182
151
|
time: number;
|
|
183
152
|
firstToken?: number;
|
|
184
|
-
decode?: Record<DecodeKind, number>;
|
|
185
|
-
blocks?: DecodeCounts;
|
|
186
|
-
block?: {
|
|
187
|
-
kind: DecodeKind;
|
|
188
|
-
since: number;
|
|
189
|
-
};
|
|
190
153
|
};
|
|
191
154
|
/**
|
|
192
155
|
* Tool callId → the call's name, start instant, and raw arguments, armed by
|
|
@@ -292,8 +255,7 @@ type Category = 'user' | 'inject' | 'skill' | 'assistant' | 'tool';
|
|
|
292
255
|
/**
|
|
293
256
|
* One live system-prompt node (Snapshot.systems) — the harness models the
|
|
294
257
|
* system prompt as a surface node, so its TEXT is fetched on demand from the
|
|
295
|
-
* event at `seq
|
|
296
|
-
* whose envelope carried `header.system`. `tokens` is the node's heuristic
|
|
258
|
+
* `system/message` event at `seq`. `tokens` is the node's heuristic
|
|
297
259
|
* price (0 for a dormant empty node, which the harness reads as "no system
|
|
298
260
|
* prompt"); the effective figure is the LAST node with `tokens > 0`.
|
|
299
261
|
*/
|
|
@@ -452,9 +414,9 @@ interface Snapshot {
|
|
|
452
414
|
timing?: TimingTotals;
|
|
453
415
|
/**
|
|
454
416
|
* The live system-prompt nodes, oldest first — the browser's per-step source
|
|
455
|
-
* for the System section. Absent
|
|
456
|
-
*
|
|
457
|
-
* own `systemTokens`, the
|
|
417
|
+
* for the System section. Absent on rows folded before this field existed
|
|
418
|
+
* (older plugin builds; the client then falls back to the header epoch's
|
|
419
|
+
* own `systemTokens`, the legacy wire shape those builds served).
|
|
458
420
|
*/
|
|
459
421
|
systems?: SystemPromptNode[];
|
|
460
422
|
/**
|
|
@@ -536,7 +498,7 @@ interface ContextTimelineDetail {
|
|
|
536
498
|
* One executed file operation (a settled file-tool call with a resolved
|
|
537
499
|
* target), folded host-side from the durable tool lifecycle: the call's
|
|
538
500
|
* name+arguments (`tool/call`), the result's presentation meta and error
|
|
539
|
-
* (`tool/result`), or a nested Code-Mode settle (`tool/
|
|
501
|
+
* (`tool/result`), or a nested Code-Mode settle (`tool/ptc-dispatch`,
|
|
540
502
|
* located on its parent run_code result via `parent` + `program`).
|
|
541
503
|
*
|
|
542
504
|
* `gone` is NOT host-stamped: the client joins it from the detail's archive
|
|
@@ -604,10 +566,9 @@ interface ToolTimingTotals {
|
|
|
604
566
|
* Whole-session timing totals, host-folded from the durable `step/start` /
|
|
605
567
|
* `step/end` / `tool/call` / `tool/result` lifecycle plus the model call's
|
|
606
568
|
* first token (running totals over the COMPLETE session log — the same
|
|
607
|
-
* never-trimmed framing as `cost`). The first token comes from
|
|
608
|
-
* `assistant/
|
|
609
|
-
*
|
|
610
|
-
* V2+ settlement) — whichever the log carries, matching the harness's own
|
|
569
|
+
* never-trimmed framing as `cost`). The first token comes from the call's
|
|
570
|
+
* own embedded stream (`assistant/message.data.stream` /
|
|
571
|
+
* `assistant/attempt.data.stream`), matching the harness's own
|
|
611
572
|
* session-stats fold. Durations are wall-clock milliseconds: `wallMs` sums
|
|
612
573
|
* whole steps, `ttftMs` the step-start → first-token slice (the model wait)
|
|
613
574
|
* and `genMs` the first-token → assistant-message slice (the generation) —
|
|
@@ -878,7 +839,33 @@ export interface Config {
|
|
|
878
839
|
insightsEntry?: InsightsEntry;
|
|
879
840
|
}
|
|
880
841
|
/** The cordis `Config` validator and the Config-form generation's served schema. */
|
|
881
|
-
export declare const Config: z$1<
|
|
842
|
+
export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
|
|
843
|
+
maxRequestSteps: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
844
|
+
maxKeptTurns: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
845
|
+
maxEvents: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
846
|
+
maxNodes: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
847
|
+
maxArchiveNodes: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
848
|
+
maxFileOps: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
849
|
+
defaultPlacement: z$1<"all" | "sidebar" | "tab", "all" | "sidebar" | "tab", Mode>;
|
|
850
|
+
defaultGranularity: z$1<"step" | "turn", "step" | "turn", Mode>;
|
|
851
|
+
defaultTrendMode: z$1<"delta" | "total", "delta" | "total", Mode>;
|
|
852
|
+
defaultToolSort: z$1<"count" | "name" | "size", "count" | "name" | "size", Mode>;
|
|
853
|
+
defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", Mode>;
|
|
854
|
+
insightsEntry: z$1<"hide" | "show", "hide" | "show", Mode>;
|
|
855
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
856
|
+
maxRequestSteps: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
857
|
+
maxKeptTurns: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
858
|
+
maxEvents: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
859
|
+
maxNodes: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
860
|
+
maxArchiveNodes: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
861
|
+
maxFileOps: z$1<number, number, Mode extends "volatile" | "volatile-defined" ? "volatile-defined" : "defined">;
|
|
862
|
+
defaultPlacement: z$1<"all" | "sidebar" | "tab", "all" | "sidebar" | "tab", Mode>;
|
|
863
|
+
defaultGranularity: z$1<"step" | "turn", "step" | "turn", Mode>;
|
|
864
|
+
defaultTrendMode: z$1<"delta" | "total", "delta" | "total", Mode>;
|
|
865
|
+
defaultToolSort: z$1<"count" | "name" | "size", "count" | "name" | "size", Mode>;
|
|
866
|
+
defaultFileSort: z$1<"count" | "latest" | "path", "count" | "latest" | "path", Mode>;
|
|
867
|
+
insightsEntry: z$1<"hide" | "show", "hide" | "show", Mode>;
|
|
868
|
+
}>>, "plain">;
|
|
882
869
|
//#endregion
|
|
883
870
|
//#region src/host/index.d.ts
|
|
884
871
|
export declare const name = "dsh-context";
|
package/lib/index.js
CHANGED
|
@@ -330,30 +330,28 @@ function isInjection(source) {
|
|
|
330
330
|
//#region src/host/logShapes.ts
|
|
331
331
|
/**
|
|
332
332
|
* Shape-driven readers over the durable session-event vocabulary — the ONE
|
|
333
|
-
* place the plugin
|
|
333
|
+
* place the plugin's log spellings meet. The supported range (dsh
|
|
334
|
+
* 0.1.5-rc.1+, session formats V3/V4) speaks ONE dialect:
|
|
335
|
+
* `system/message` surface nodes, `assistant/message.data.stream` /
|
|
336
|
+
* `assistant/attempt.data.stream` (packed delta runs plus raw chunk
|
|
337
|
+
* records), `SurfaceOp { startSeq, endSeq }`, `tool/ptc-dispatch`.
|
|
334
338
|
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
* exclusive within it, and a deployment's version probe can be wrong (a
|
|
344
|
-
* healed profile mirror may name a different release than the running
|
|
345
|
-
* harness). Every reader is total over untrusted input — a malformed record
|
|
346
|
-
* yields "nothing here", never a throw (the projection registry drives the
|
|
347
|
-
* fold without an error boundary; one throw stalls the unit's push feed and
|
|
348
|
-
* the browser waits on "loading" forever).
|
|
339
|
+
* The fold still reads SHAPES, never a detected harness version: the raw log
|
|
340
|
+
* is untrusted input at every layer, and the supported harness refuses —
|
|
341
|
+
* never rewrites — a legacy-format log, so anything that reaches these
|
|
342
|
+
* readers is current-dialect or hostile. Every reader is total over
|
|
343
|
+
* untrusted input — a malformed record yields "nothing here", never a throw
|
|
344
|
+
* (the projection registry drives the fold without an error boundary; one
|
|
345
|
+
* throw stalls the unit's push feed and the browser waits on "loading"
|
|
346
|
+
* forever).
|
|
349
347
|
*
|
|
350
348
|
* @module dsh-context/host/log-shapes
|
|
351
349
|
*/
|
|
352
350
|
/**
|
|
353
|
-
* Whether one raw stream chunk carries a token delta — the first-token
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
351
|
+
* Whether one raw stream chunk carries a token delta — the first-token
|
|
352
|
+
* marker, mirroring dsh-llm's `isTokenDelta` (a non-empty text or reasoning
|
|
353
|
+
* fragment, or any Tool-call delta carrying arguments or a name); a
|
|
354
|
+
* malformed chunk is simply not a token.
|
|
357
355
|
*/
|
|
358
356
|
function isTokenChunk(chunk) {
|
|
359
357
|
if (chunk === null || typeof chunk !== "object") return false;
|
|
@@ -375,9 +373,7 @@ function decodeKindOfBlock(blockType) {
|
|
|
375
373
|
* Per-kind decode spans AND counted `block-start` markers inside one embedded
|
|
376
374
|
* assistant stream, tiling [first block-start, endTime]: each `block-start`
|
|
377
375
|
* record owns the interval up to the next one, the last one up to `endTime`.
|
|
378
|
-
*
|
|
379
|
-
* (`assistant/message.data.stream`) instead of separate `assistant/chunk`
|
|
380
|
-
* events. Total over untrusted input — a malformed record is skipped whole (a
|
|
376
|
+
* Total over untrusted input — a malformed record is skipped whole (a
|
|
381
377
|
* marker with an unusable time anchors no span and counts nothing), a
|
|
382
378
|
* non-finite boundary yields zero, and a stream with no marker (or not an
|
|
383
379
|
* array) yields all zeros.
|
|
@@ -441,9 +437,8 @@ function runFirstTokenTime(record) {
|
|
|
441
437
|
}
|
|
442
438
|
/**
|
|
443
439
|
* The first token's instant inside an embedded assistant stream
|
|
444
|
-
* (`assistant/message.data.stream`, `assistant/attempt.data.stream`
|
|
445
|
-
*
|
|
446
|
-
* when the stream carries no token. Mirrors dsh-llm's
|
|
440
|
+
* (`assistant/message.data.stream`, `assistant/attempt.data.stream`), or
|
|
441
|
+
* undefined when the stream carries no token. Mirrors dsh-llm's
|
|
447
442
|
* `assistantStreamFirstTokenTime` over the compact record union.
|
|
448
443
|
*/
|
|
449
444
|
function firstTokenTimeOfStream(stream) {
|
|
@@ -463,16 +458,14 @@ function firstTokenTimeOfStream(stream) {
|
|
|
463
458
|
/**
|
|
464
459
|
* The inclusive surface range a replacement op covers, or null for `append`
|
|
465
460
|
* and for any unrecognized/hostile op (which the fold treats as an append).
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
* with one good and one malformed endpoint degrades to append.
|
|
461
|
+
* The `startSeq`/`endSeq` endpoints are each accepted only as a finite
|
|
462
|
+
* number, so a hostile op with one malformed endpoint degrades to append.
|
|
469
463
|
*/
|
|
470
464
|
function replaceRangeOf(surfaceOp) {
|
|
471
465
|
if (surfaceOp === null || typeof surfaceOp !== "object") return null;
|
|
472
466
|
const op = surfaceOp;
|
|
473
467
|
if (op.op !== "replace") return null;
|
|
474
|
-
const
|
|
475
|
-
const end = typeof op.endSeq === "number" ? op.endSeq : op.end;
|
|
468
|
+
const { startSeq: start, endSeq: end } = op;
|
|
476
469
|
if (typeof start !== "number" || !Number.isFinite(start)) return null;
|
|
477
470
|
if (typeof end !== "number" || !Number.isFinite(end)) return null;
|
|
478
471
|
return {
|
|
@@ -903,8 +896,10 @@ function removeSurfaceSeqs(st, claimed, goneSeq) {
|
|
|
903
896
|
/**
|
|
904
897
|
* The message nested under an event payload's `message` field
|
|
905
898
|
* (`system/message`, `assistant/message`, `tool/result`) — read structurally
|
|
906
|
-
*
|
|
907
|
-
*
|
|
899
|
+
* because the fold needs a TOTAL read over untrusted payloads: a malformed
|
|
900
|
+
* message reads null here, never throws or guesses a shape. Purely a type
|
|
901
|
+
* cast: `deriveEventMessage` returns `event.data` for a user/message (no
|
|
902
|
+
* `data.message` indirection), so its result feeds every other case.
|
|
908
903
|
*/
|
|
909
904
|
function messageOf$1(data) {
|
|
910
905
|
const message = data?.message;
|
|
@@ -1257,20 +1252,6 @@ function applyTimeline(state, event, bounds) {
|
|
|
1257
1252
|
const tools = Array.isArray(header.tools) ? header.tools : [];
|
|
1258
1253
|
const s = ensure(["events"]);
|
|
1259
1254
|
s.toolsTokens = estimateToolsTotal(tools);
|
|
1260
|
-
const systemText = header.system;
|
|
1261
|
-
if (typeof systemText === "string" && systemText !== "") {
|
|
1262
|
-
s.systems = [{
|
|
1263
|
-
seq: event.seq,
|
|
1264
|
-
time: event.time,
|
|
1265
|
-
tokens: estimateSystemTokens(systemText)
|
|
1266
|
-
}];
|
|
1267
|
-
s.systemsFromHeader = true;
|
|
1268
|
-
s.systemTokens = systemTokensOf(s.systems);
|
|
1269
|
-
} else if (s.systemsFromHeader === true) {
|
|
1270
|
-
s.systems = [];
|
|
1271
|
-
delete s.systemsFromHeader;
|
|
1272
|
-
s.systemTokens = 0;
|
|
1273
|
-
}
|
|
1274
1255
|
if (header.config && typeof header.config.model === "string") s.model = header.config.model;
|
|
1275
1256
|
if (header.config && typeof header.config.provider === "string") s.provider = header.config.provider;
|
|
1276
1257
|
if ((data?.reason === "change" || data?.reason === "resume") && s.model && s.lastModel && s.model !== s.lastModel) {
|
|
@@ -1301,7 +1282,6 @@ function applyTimeline(state, event, bounds) {
|
|
|
1301
1282
|
for (const n of s.surface) if (n.seq >= op.start && n.seq <= op.end) claimed.add(n.seq);
|
|
1302
1283
|
if (removeSurfaceSeqs(s, claimed, event.seq).length > 0) bumpDetailRev(s);
|
|
1303
1284
|
}
|
|
1304
|
-
delete s.systemsFromHeader;
|
|
1305
1285
|
pushSystem(s, {
|
|
1306
1286
|
seq: event.seq,
|
|
1307
1287
|
time: event.time,
|
|
@@ -1327,7 +1307,6 @@ function applyTimeline(state, event, bounds) {
|
|
|
1327
1307
|
};
|
|
1328
1308
|
}
|
|
1329
1309
|
break;
|
|
1330
|
-
case "tool/code-dispatch":
|
|
1331
1310
|
case "tool/ptc-dispatch": {
|
|
1332
1311
|
const rootCallId = data?.rootCallId;
|
|
1333
1312
|
const name = data?.name;
|
|
@@ -1344,47 +1323,6 @@ function applyTimeline(state, event, bounds) {
|
|
|
1344
1323
|
}
|
|
1345
1324
|
break;
|
|
1346
1325
|
}
|
|
1347
|
-
case "assistant/chunk": {
|
|
1348
|
-
const start = state.stepStart;
|
|
1349
|
-
if (start === void 0) return state;
|
|
1350
|
-
const chunk = data?.chunk;
|
|
1351
|
-
if (chunk !== null && typeof chunk === "object" && chunk.type === "block-start") {
|
|
1352
|
-
const kind = decodeKindOfBlock(chunk.blockType);
|
|
1353
|
-
if (start.block === void 0 && kind === void 0) return state;
|
|
1354
|
-
const s = ensure([]);
|
|
1355
|
-
const decode = { ...start.decode ?? {
|
|
1356
|
-
reasoning: 0,
|
|
1357
|
-
text: 0,
|
|
1358
|
-
toolarg: 0
|
|
1359
|
-
} };
|
|
1360
|
-
if (start.block !== void 0) decode[start.block.kind] += durOf(start.block.since, event.time);
|
|
1361
|
-
const blocks = { ...start.blocks ?? {
|
|
1362
|
-
reasoning: 0,
|
|
1363
|
-
text: 0,
|
|
1364
|
-
toolarg: 0
|
|
1365
|
-
} };
|
|
1366
|
-
if (kind !== void 0) blocks[kind] += 1;
|
|
1367
|
-
s.stepStart = {
|
|
1368
|
-
time: start.time,
|
|
1369
|
-
...start.firstToken !== void 0 ? { firstToken: start.firstToken } : {},
|
|
1370
|
-
decode,
|
|
1371
|
-
blocks,
|
|
1372
|
-
...kind !== void 0 ? { block: {
|
|
1373
|
-
kind,
|
|
1374
|
-
since: event.time
|
|
1375
|
-
} } : {}
|
|
1376
|
-
};
|
|
1377
|
-
break;
|
|
1378
|
-
}
|
|
1379
|
-
if (start.firstToken !== void 0) return state;
|
|
1380
|
-
if (!isTokenChunk(data?.chunk)) return state;
|
|
1381
|
-
const s = ensure([]);
|
|
1382
|
-
s.stepStart = {
|
|
1383
|
-
...start,
|
|
1384
|
-
firstToken: event.time
|
|
1385
|
-
};
|
|
1386
|
-
break;
|
|
1387
|
-
}
|
|
1388
1326
|
case "assistant/attempt": {
|
|
1389
1327
|
const start = state.stepStart;
|
|
1390
1328
|
if (start === void 0 || start.firstToken !== void 0) return state;
|
|
@@ -1426,7 +1364,7 @@ function applyTimeline(state, event, bounds) {
|
|
|
1426
1364
|
seq: event.seq,
|
|
1427
1365
|
time: event.time,
|
|
1428
1366
|
kind: "inject",
|
|
1429
|
-
form: source.form
|
|
1367
|
+
form: typeof source.form === "string" && source.form !== "" ? source.form : "context",
|
|
1430
1368
|
tokens: node.tokens
|
|
1431
1369
|
};
|
|
1432
1370
|
if (source.kind === "skill-invocation") {
|
|
@@ -1565,14 +1503,8 @@ function applyTimeline(state, event, bounds) {
|
|
|
1565
1503
|
timing.speedMs = (timing.speedMs ?? 0) + durOf(firstToken, event.time);
|
|
1566
1504
|
timing.speedTokens = (timing.speedTokens ?? 0) + output;
|
|
1567
1505
|
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
if (stepStart.block !== void 0) decode[stepStart.block.kind] += durOf(stepStart.block.since, event.time);
|
|
1571
|
-
for (const kind of DECODE_KINDS) addDecode(timing, kind, decode[kind], stepStart.blocks?.[kind] ?? 0);
|
|
1572
|
-
} else {
|
|
1573
|
-
const tally = decodeTallyOfStream(data?.stream, event.time);
|
|
1574
|
-
for (const kind of DECODE_KINDS) addDecode(timing, kind, tally.spans[kind], tally.blocks[kind]);
|
|
1575
|
-
}
|
|
1506
|
+
const tally = decodeTallyOfStream(data?.stream, event.time);
|
|
1507
|
+
for (const kind of DECODE_KINDS) addDecode(timing, kind, tally.spans[kind], tally.blocks[kind]);
|
|
1576
1508
|
}
|
|
1577
1509
|
}
|
|
1578
1510
|
const asstMsg = deriveEventMessage(event);
|
|
@@ -2345,10 +2277,29 @@ function headerOf(record) {
|
|
|
2345
2277
|
if (typeof header.id !== "string" || header.id === "") return null;
|
|
2346
2278
|
return header;
|
|
2347
2279
|
}
|
|
2280
|
+
/** The probe keys: the projection keys the cache must already serve. */
|
|
2281
|
+
const PROBE_KEYS = ["contextActivity", "contextTimeline"];
|
|
2282
|
+
/**
|
|
2283
|
+
* Probe the cache through the face the running generation serves. The older
|
|
2284
|
+
* spelling is tried first and the newer one answers the fallback: on a
|
|
2285
|
+
* 0.1.7-rc.2 cache the 3-arg call binds the branded offset onto `keys`,
|
|
2286
|
+
* where `new Set(0)` throws as soon as a served record is reached — while a
|
|
2287
|
+
* record-less session returns `undefined` without throwing, which is the
|
|
2288
|
+
* correct "not served" either way. On 0.1.5-rc.1 the 3-arg face answers
|
|
2289
|
+
* directly; if it ever throws there, the 2-arg retry degrades to the same
|
|
2290
|
+
* "not served" verdict through the caller's catch.
|
|
2291
|
+
*/
|
|
2292
|
+
function cachedSnapshotOf(cache, header) {
|
|
2293
|
+
try {
|
|
2294
|
+
return cache.cachedSnapshot(header, SessionLogOffset(0), PROBE_KEYS);
|
|
2295
|
+
} catch {
|
|
2296
|
+
return cache.cachedSnapshot(header, PROBE_KEYS);
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2348
2299
|
/** Whether the cache already serves BOTH projection rows for this header (nothing to backfill). */
|
|
2349
2300
|
function servesRows(cache, header) {
|
|
2350
2301
|
try {
|
|
2351
|
-
const values = asRecord(asRecord(cache
|
|
2302
|
+
const values = asRecord(asRecord(cachedSnapshotOf(cache, header))?.values);
|
|
2352
2303
|
return values !== null && values.contextActivity !== void 0 && values.contextTimeline !== void 0;
|
|
2353
2304
|
} catch {
|
|
2354
2305
|
return false;
|
|
@@ -2693,7 +2644,7 @@ function watchDetailChannel(ctx, bounds) {
|
|
|
2693
2644
|
* (host/fallback.ts) instead of the real folds.
|
|
2694
2645
|
*/
|
|
2695
2646
|
/** The oldest supported dsh release (see the matrix note above). */
|
|
2696
|
-
const BASELINE_DSH_VERSION = "0.1.
|
|
2647
|
+
const BASELINE_DSH_VERSION = "0.1.5-rc.1";
|
|
2697
2648
|
/**
|
|
2698
2649
|
* Release-channel rank at an equal X.Y.Z: a final release outranks its
|
|
2699
2650
|
* release candidates, which outrank betas, which outrank alphas
|
|
@@ -2815,11 +2766,11 @@ const contextHeadersSchema = z.object({ headers: z.array(z.object({
|
|
|
2815
2766
|
}).strict()) }).strict();
|
|
2816
2767
|
function recordOf(event) {
|
|
2817
2768
|
if (event.type !== "request/header") return null;
|
|
2818
|
-
const rawHeader = event.data
|
|
2769
|
+
const rawHeader = event.data?.header;
|
|
2819
2770
|
if (rawHeader === null || rawHeader === void 0 || typeof rawHeader !== "object") return null;
|
|
2820
2771
|
const header = rawHeader;
|
|
2821
2772
|
const tools = Array.isArray(header.tools) ? header.tools : [];
|
|
2822
|
-
|
|
2773
|
+
return {
|
|
2823
2774
|
seq: event.seq,
|
|
2824
2775
|
time: event.time,
|
|
2825
2776
|
tools: tools.map((t) => {
|
|
@@ -2832,8 +2783,6 @@ function recordOf(event) {
|
|
|
2832
2783
|
return entry;
|
|
2833
2784
|
})
|
|
2834
2785
|
};
|
|
2835
|
-
if (typeof header.system === "string" && header.system.length > 0) record.systemTokens = estimateSystemTokens(header.system);
|
|
2836
|
-
return record;
|
|
2837
2786
|
}
|
|
2838
2787
|
/**
|
|
2839
2788
|
* The context-headers projection unit; registered alongside the timeline unit (host/index.ts); clients read it through
|
|
@@ -3115,7 +3064,6 @@ const timelineStateSchema = z.object({
|
|
|
3115
3064
|
}).strict(),
|
|
3116
3065
|
systemTokens: z.number().int().nonnegative(),
|
|
3117
3066
|
systems: z.array(systemPromptNodeSchema).optional(),
|
|
3118
|
-
systemsFromHeader: z.literal(true).optional(),
|
|
3119
3067
|
toolsTokens: z.number().int().nonnegative(),
|
|
3120
3068
|
model: z.string().optional(),
|
|
3121
3069
|
provider: z.string().optional(),
|
|
@@ -3132,25 +3080,7 @@ const timelineStateSchema = z.object({
|
|
|
3132
3080
|
lastUser: z.string().optional(),
|
|
3133
3081
|
stepStart: z.object({
|
|
3134
3082
|
time: z.number(),
|
|
3135
|
-
firstToken: z.number().optional()
|
|
3136
|
-
decode: z.object({
|
|
3137
|
-
reasoning: z.number(),
|
|
3138
|
-
text: z.number(),
|
|
3139
|
-
toolarg: z.number()
|
|
3140
|
-
}).strict().optional(),
|
|
3141
|
-
blocks: z.object({
|
|
3142
|
-
reasoning: z.number().int(),
|
|
3143
|
-
text: z.number().int(),
|
|
3144
|
-
toolarg: z.number().int()
|
|
3145
|
-
}).strict().optional(),
|
|
3146
|
-
block: z.object({
|
|
3147
|
-
kind: z.enum([
|
|
3148
|
-
"reasoning",
|
|
3149
|
-
"text",
|
|
3150
|
-
"toolarg"
|
|
3151
|
-
]),
|
|
3152
|
-
since: z.number()
|
|
3153
|
-
}).strict().optional()
|
|
3083
|
+
firstToken: z.number().optional()
|
|
3154
3084
|
}).strict().optional(),
|
|
3155
3085
|
callNames: z.record(z.string(), z.object({
|
|
3156
3086
|
name: z.string(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-context",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.56.0",
|
|
4
4
|
"description": "A DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.",
|
|
5
5
|
"icon": "icon.svg",
|
|
6
6
|
"author": "bowenliang123",
|
|
@@ -68,10 +68,8 @@
|
|
|
68
68
|
},
|
|
69
69
|
"compatibility": {
|
|
70
70
|
"dshReleases": {
|
|
71
|
-
"0.1.2-rc.1": "compatible",
|
|
72
|
-
"0.1.3-alpha.2": "compatible",
|
|
73
71
|
"0.1.5-rc.1": "compatible",
|
|
74
|
-
"0.1.7-
|
|
72
|
+
"0.1.7-rc.2": "compatible"
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
75
|
},
|
|
@@ -90,9 +88,9 @@
|
|
|
90
88
|
},
|
|
91
89
|
"peerDependencies": {
|
|
92
90
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.
|
|
94
|
-
"@deepseek-ai/dsh-session": ">=0.1.
|
|
95
|
-
"@deepseek-ai/dsh-settings": ">=0.1.
|
|
91
|
+
"@deepseek-ai/dsh-client-ui-primitives": ">=0.1.5-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-session": ">=0.1.5-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-settings": ">=0.1.5-rc.1",
|
|
96
94
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
97
95
|
"react": "^18.3.1"
|
|
98
96
|
},
|
|
@@ -106,15 +104,16 @@
|
|
|
106
104
|
},
|
|
107
105
|
"devDependencies": {
|
|
108
106
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
109
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.
|
|
110
|
-
"@deepseek-ai/dsh-invariants": "0.1.
|
|
111
|
-
"@deepseek-ai/dsh-scope": "0.1.
|
|
112
|
-
"@deepseek-ai/dsh-session": "0.1.
|
|
113
|
-
"@deepseek-ai/dsh-session-projection": "0.1.
|
|
114
|
-
"@deepseek-ai/dsh-settings": "0.1.
|
|
107
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-invariants": "0.1.5-rc.1",
|
|
109
|
+
"@deepseek-ai/dsh-scope": "0.1.5-rc.1",
|
|
110
|
+
"@deepseek-ai/dsh-session": "0.1.5-rc.1",
|
|
111
|
+
"@deepseek-ai/dsh-session-projection": "0.1.5-rc.1",
|
|
112
|
+
"@deepseek-ai/dsh-settings": "0.1.5-rc.1",
|
|
115
113
|
"@deepseek-ai/dsh-util-workspace-path": "0.1.5-rc.1",
|
|
116
114
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
117
115
|
"@opencode-ai/models": "^0.0.72",
|
|
116
|
+
"@shikijs/langs": "^4.3.1",
|
|
118
117
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
119
118
|
"@tailwindcss/node": "4.3.3",
|
|
120
119
|
"@tailwindcss/oxide": "4.3.3",
|
|
@@ -122,15 +121,30 @@
|
|
|
122
121
|
"@types/react": "^18.3.31",
|
|
123
122
|
"@types/react-dom": "^18.3.7",
|
|
124
123
|
"@vitest/coverage-v8": "^4.1.11",
|
|
124
|
+
"anser": "^2.3.5",
|
|
125
|
+
"clsx": "^2.0.0",
|
|
125
126
|
"eslint-plugin-sonarjs": "^4.2.0",
|
|
126
127
|
"husky": "^9.1.7",
|
|
127
128
|
"jsdom": "^30.0.1",
|
|
129
|
+
"katex": "^0.16.47",
|
|
128
130
|
"lightningcss": "1.32.0",
|
|
131
|
+
"mdast-util-from-markdown": "^2.0.3",
|
|
132
|
+
"mdast-util-gfm": "^3.1.0",
|
|
133
|
+
"mdast-util-math": "^3.0.0",
|
|
134
|
+
"micromark-core-commonmark": "^2.0.3",
|
|
135
|
+
"micromark-extension-gfm": "^3.0.0",
|
|
136
|
+
"micromark-extension-math": "^3.1.0",
|
|
137
|
+
"micromark-factory-space": "^2.0.1",
|
|
138
|
+
"micromark-util-character": "^2.1.1",
|
|
139
|
+
"micromark-util-classify-character": "^2.0.1",
|
|
140
|
+
"micromark-util-sanitize-uri": "^2.0.1",
|
|
141
|
+
"micromark-util-symbol": "^2.0.1",
|
|
129
142
|
"oxlint": "1.82.0",
|
|
130
143
|
"oxlint-tsgolint": "7.0.2001",
|
|
131
144
|
"playwright-core": "^1.62.1",
|
|
132
145
|
"react": "^18.3.1",
|
|
133
146
|
"react-dom": "^18.3.1",
|
|
147
|
+
"shiki": "^4.3.1",
|
|
134
148
|
"simple-icons": "16.31.0",
|
|
135
149
|
"tailwindcss": "4.3.3",
|
|
136
150
|
"tsdown": "^0.23.0",
|