dsh-advisor 0.1.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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +7 -0
  3. package/README.md +303 -0
  4. package/README.zh.md +166 -0
  5. package/cordis.patch.yml +6 -0
  6. package/lib/advisor-runtime.d.ts +242 -0
  7. package/lib/advisor-runtime.js +662 -0
  8. package/lib/advisor-runtime.js.map +1 -0
  9. package/lib/client/advisor-card.d.ts +90 -0
  10. package/lib/client/advisor-store.d.ts +310 -0
  11. package/lib/client/index.d.ts +39 -0
  12. package/lib/client/locales.d.ts +40 -0
  13. package/lib/client.d.ts +1 -0
  14. package/lib/client.js +840 -0
  15. package/lib/commands.d.ts +136 -0
  16. package/lib/commands.js +185 -0
  17. package/lib/commands.js.map +1 -0
  18. package/lib/config.d.ts +74 -0
  19. package/lib/config.js +93 -0
  20. package/lib/config.js.map +1 -0
  21. package/lib/delivery.d.ts +129 -0
  22. package/lib/delivery.js +169 -0
  23. package/lib/delivery.js.map +1 -0
  24. package/lib/emission-guard.d.ts +99 -0
  25. package/lib/emission-guard.js +155 -0
  26. package/lib/emission-guard.js.map +1 -0
  27. package/lib/gateway.d.ts +116 -0
  28. package/lib/gateway.js +214 -0
  29. package/lib/gateway.js.map +1 -0
  30. package/lib/index.d.ts +48 -0
  31. package/lib/index.js +485 -0
  32. package/lib/index.js.map +1 -0
  33. package/lib/kinds.d.ts +38 -0
  34. package/lib/kinds.js +24 -0
  35. package/lib/kinds.js.map +1 -0
  36. package/lib/prompts.d.ts +22 -0
  37. package/lib/prompts.js +38 -0
  38. package/lib/prompts.js.map +1 -0
  39. package/lib/settings.d.ts +96 -0
  40. package/lib/settings.js +141 -0
  41. package/lib/settings.js.map +1 -0
  42. package/lib/transcript.d.ts +257 -0
  43. package/lib/transcript.js +530 -0
  44. package/lib/transcript.js.map +1 -0
  45. package/package.json +90 -0
  46. package/scripts/build-client.mjs +268 -0
@@ -0,0 +1,530 @@
1
+ /**
2
+ * Session observer + bounded delta renderer (spec §2 S2, §4 mapping table,
3
+ * §6 self-review exclusion, §8.3 KD-3, §8.5 KD-5).
4
+ *
5
+ * `DeltaRenderer` is the pure transcript core: a cursor over the session event
6
+ * log plus a fingerprint of the delivered prefix. `update(events)` extracts
7
+ * the newly appended messages, excludes advisor-source messages (self-review
8
+ * guard), and renders a role-annotated markdown delta bounded by the
9
+ * `maxDeltaMessages` window. A prefix rewrite — a `compact/*` event, a
10
+ * `user/message` with `surfaceOp.op === 'replace'`, or a fingerprint mismatch
11
+ * (defensive fallback) — resets the cursor and replays the full post-rewrite
12
+ * surface on the next update.
13
+ *
14
+ * `SessionTranscriptObserver` is the per-session wiring unit: it owns one
15
+ * `DeltaRenderer` per session id and dispatches `session/event` tuples to
16
+ * them. It has TWO trigger modes (KD-N4-5):
17
+ *
18
+ * 1. **turn/end** (standard turn-driven sessions): renders only on a stepped
19
+ * `turn/end` whose `reason.kind` is reviewable (`completed` | `max-tokens`
20
+ * | `error`; spec §4 — skip `aborted`/`blocked`/`interrupted`, i.e. do not
21
+ * critique user-cut-short turns). Byte-identical behavior — the original
22
+ * single-trigger path.
23
+ * 2. **agent reply complete** (harness/agentic sessions, which never emit
24
+ * `turn/end`): fires on human-input arrival (`user/message` with
25
+ * `source.kind === 'user'`, or `agent/inbox/spliced` whose `inserted`
26
+ * carries a message with `source.kind === 'user'` — inbox-spliced input
27
+ * may commit as that event first and never re-emit as `user/message`).
28
+ * Non-user inbox splices (the advisor's own inject/steer deliveries,
29
+ * workspace/tool/empty splices) never trigger (C-1 self-trigger fix).
30
+ * Before rendering,
31
+ * a read-only predicate checks for an unreviewed non-advisor
32
+ * `assistant/message` since the renderer cursor; on a miss the cursor is
33
+ * untouched (the first user input of a session neither triggers nor
34
+ * advances). Append-type triggers pass `events` minus the trigger itself
35
+ * (the arriving input opens the next round); rewrite-type triggers
36
+ * (compact summary replace) pass the full log to trigger the KD-5 replay.
37
+ * Both modes share the same renderer/cursor, so the cursor advance dedupes
38
+ * (one delta per completed round), and both call `onSteppedTurnEnd` (the
39
+ * immuneTurns countdown — T6) before rendering.
40
+ *
41
+ * **Mode latch**: once a session has produced ANY `turn/end` event
42
+ * (reviewable or not), the new gate sleeps for it — the session is a
43
+ * standard turn-driven one and keeps verbatim behavior, including spec §4
44
+ * skip-aborted (a cut-short first turn's unreviewed increment must not be
45
+ * supplementarily reviewed by the new gate). Harness/agentic sessions never
46
+ * emit `turn/end`, so their latch never arms.
47
+ *
48
+ * It also exposes the T6 delivery hooks: `onSteppedTurnEnd` (one completed
49
+ * stepped primary turn — the immuneTurns countdown) and `onRewrite` (a
50
+ * compact/replace event — the KD-5 latch reset). `index.ts` binds the cordis
51
+ * `session/event` / `session/disposed` / `agent/disposed` listeners into an
52
+ * instance of this class.
53
+ *
54
+ * @module dsh-advisor/transcript
55
+ */
56
+ import { deriveEventMessage, foldSurface, isSurfaceEvent, } from '@deepseek-ai/dsh-session';
57
+ import { isAdvisorMessage } from './kinds.js';
58
+ /** Default delta window (KD-3). */
59
+ export const DEFAULT_MAX_DELTA_MESSAGES = 60;
60
+ /** Marker line prepended when a rendered delta omits earlier messages (KD-3). */
61
+ export const TRUNCATION_MARKER = '… <earlier messages omitted>';
62
+ const SESSION_UPDATE_HEADING = '### Session update';
63
+ // ---------------------------------------------------------------------------
64
+ // Pure helpers
65
+ // ---------------------------------------------------------------------------
66
+ /** Whether an event resets the incremental fold (KD-5 triggers, superset). */
67
+ function isRewriteEvent(event) {
68
+ // compact/start | compact/summary | compact/end | compact/prune — log-only
69
+ // events declared by @deepseek-ai/dsh-compact (not in this package's
70
+ // dependency closure; matched by type string, per the plan's
71
+ // implementation-time verification item 3).
72
+ if (event.type.startsWith('compact/'))
73
+ return true;
74
+ // Any surface event that replaced a range (the compaction summary
75
+ // `user/message`, or a tool/result content rewrite) invalidates the
76
+ // incremental append fold: a rewrite must rebuild the surface from scratch.
77
+ // Superset of KD-5's `user/message` replace — a replace on any surface
78
+ // type resets, which keeps the fold correct for every rewrite dsh can emit.
79
+ if (!isSurfaceEvent(event))
80
+ return false;
81
+ return event.surfaceOp !== 'append';
82
+ }
83
+ /**
84
+ * Fingerprint of the delivered log prefix (`events[0..length)`): the message
85
+ * identities derived from those events. A hidden rewrite of delivered history
86
+ * changes those identities, so a mismatch forces a reset + full replay.
87
+ *
88
+ * In dsh, events are immutable and append-only — every real rewrite arrives
89
+ * as a visible `compact/*` or replace event (the authoritative triggers), so
90
+ * this check is the defensive fallback the spec describes.
91
+ *
92
+ * simplify: O(length) per update over the delivered prefix. A rolling hash
93
+ * over a bounded suffix would bound the cost if sessions grow very large; the
94
+ * authoritative rewrite triggers already reset without this check.
95
+ */
96
+ function fingerprintOf(events, length) {
97
+ let hash = 0;
98
+ for (let index = 0; index < length; index++) {
99
+ const message = deriveEventMessage(events[index]);
100
+ const id = message?.id ?? `e${index}`;
101
+ for (let i = 0; i < id.length; i++) {
102
+ hash = (hash * 31 + id.charCodeAt(i)) | 0;
103
+ }
104
+ }
105
+ return hash.toString(36);
106
+ }
107
+ /** Visible text of one content block (tool-result content is unwrapped). */
108
+ function blockText(block) {
109
+ switch (block.type) {
110
+ case 'text':
111
+ return block.text;
112
+ case 'tool-result':
113
+ return block.content.map(blockText).join('\n');
114
+ default:
115
+ // reasoning / tool-call / unknown extensions carry no rendered text here.
116
+ return '';
117
+ }
118
+ }
119
+ /**
120
+ * Render one message as a role-annotated markdown entry: `**user:**` /
121
+ * `**agent:**` labels (spec §4), assistant text plus tool calls (tool intent),
122
+ * tool results tagged `[tool result]`, reasoning excluded (MVP).
123
+ */
124
+ function renderMessage(message) {
125
+ if (message.role === 'user') {
126
+ const value = message.content.map(blockText).filter((part) => part.length > 0).join('\n');
127
+ if (message.source.kind === 'tool') {
128
+ return value.length > 0 ? `**user**: [tool result] ${value}` : '**user**: [tool result] <empty>';
129
+ }
130
+ return value.length > 0 ? `**user**: ${value}` : '**user**: <empty>';
131
+ }
132
+ const parts = [];
133
+ for (const block of message.content) {
134
+ switch (block.type) {
135
+ case 'text':
136
+ if (block.text.length > 0)
137
+ parts.push(block.text);
138
+ break;
139
+ case 'tool-call':
140
+ parts.push(`- tool call: ${block.name}(${block.arguments})`);
141
+ break;
142
+ case 'reasoning':
143
+ break; // reasoning excluded in the MVP delta
144
+ default:
145
+ break;
146
+ }
147
+ }
148
+ return parts.length > 0 ? `**agent**: ${parts.join('\n')}` : '**agent**: <empty>';
149
+ }
150
+ /**
151
+ * Find the latest closed turn that entered at least one model step, ignoring
152
+ * balanced no-step turns produced by rejection, empty input, or cancellation.
153
+ * Vendored locally: `@deepseek-ai/dsh-session` removed this export in the
154
+ * 20260811 snapshot (packages/core/session/src/index.ts) — no replacement
155
+ * was provided, and the event vocabulary it scans (`step/start`, `turn/end`)
156
+ * is unchanged, so the original semantics carry over verbatim.
157
+ * @param events - session events, or an owned suffix, to inspect.
158
+ * @returns the latest matching turn end, or `undefined`.
159
+ */
160
+ function findLastMessageTurnEnd(events) {
161
+ const steppedTurns = new Set();
162
+ let latest;
163
+ for (const event of events) {
164
+ if (event.type === 'step/start') {
165
+ steppedTurns.add(event.data.turn);
166
+ continue;
167
+ }
168
+ if (event.type === 'turn/end' && steppedTurns.delete(event.data.turn))
169
+ latest = event;
170
+ }
171
+ return latest;
172
+ }
173
+ // ---------------------------------------------------------------------------
174
+ // DeltaRenderer
175
+ // ---------------------------------------------------------------------------
176
+ /**
177
+ * Cursor + fingerprint bookkeeping over one session's event log.
178
+ *
179
+ * The renderer consumes the session event log (the full `session.events`
180
+ * snapshot on each call — the cordis wiring passes the live log). It keeps:
181
+ * - `cursor` — how many log events are consumed (seqs are contiguous from 0,
182
+ * so this equals the next unprocessed seq);
183
+ * - `surface` / `messages` — the current ordered surface of derived
184
+ * non-advisor messages (seqs + messages), maintained incrementally for
185
+ * appends and rebuilt from a full fold after a reset;
186
+ * - `deliveredFingerprint` — fingerprint of the delivered prefix, detecting a
187
+ * hidden rewrite;
188
+ * - `droppedPrefix` — whether messages before the bounded window were dropped
189
+ * (drives the truncation marker on replay renders).
190
+ */
191
+ export class DeltaRenderer {
192
+ maxDeltaMessages;
193
+ cursor = 0;
194
+ surface = [];
195
+ messages = new Map();
196
+ deliveredFingerprint;
197
+ droppedPrefix = false;
198
+ constructor(options) {
199
+ this.maxDeltaMessages = options?.maxDeltaMessages ?? DEFAULT_MAX_DELTA_MESSAGES;
200
+ }
201
+ /**
202
+ * Update the bounded message window (live config — settings onChange, plan
203
+ * dsh-advisor-settings-n2 T1). Existing fold state is kept; the new bound
204
+ * applies from the next render on.
205
+ */
206
+ setMaxDeltaMessages(value) {
207
+ this.maxDeltaMessages = value;
208
+ }
209
+ /**
210
+ * Process a session event log snapshot and return the next delta, or
211
+ * `undefined` when no new (renderable) content was appended.
212
+ *
213
+ * `skipLast` treats the final log event as excluded — the arriving trigger
214
+ * of an append-type review (qc3 F1): equivalent to the caller slicing
215
+ * `events.slice(0, events.length - 1)` WITHOUT the O(full-log) shallow copy
216
+ * the reply-complete gate used to pay on every review. The excluded event
217
+ * must be the last log entry (the wiring guarantees it).
218
+ *
219
+ * - Detects a reset: a rewrite event (`compact/*`, replace surface op) in
220
+ * the unconsumed portion, a shorter log than the cursor, or a delivered
221
+ * prefix whose fingerprint changed. On reset the cursor rewinds to 0 and
222
+ * the full post-rewrite surface is replayed (bounded by KD-3).
223
+ * - Otherwise appends the new events, extracts their messages (advisor
224
+ * excluded), and renders only those (incremental delta).
225
+ */
226
+ update(events, skipLast = false) {
227
+ const effectiveLength = skipLast ? events.length - 1 : events.length;
228
+ let replay = effectiveLength < this.cursor;
229
+ if (!replay) {
230
+ const fresh = events.slice(this.cursor, effectiveLength);
231
+ replay = fresh.some(isRewriteEvent);
232
+ }
233
+ if (!replay && this.cursor > 0 && this.deliveredFingerprint !== undefined) {
234
+ replay = fingerprintOf(events, this.cursor) !== this.deliveredFingerprint;
235
+ }
236
+ let added = [];
237
+ if (replay) {
238
+ this.reset();
239
+ this.rebuild(events, effectiveLength);
240
+ }
241
+ else {
242
+ added = this.append(events, this.cursor, effectiveLength);
243
+ }
244
+ this.cursor = effectiveLength;
245
+ this.deliveredFingerprint = fingerprintOf(events, this.cursor);
246
+ return replay ? this.renderSurface() : this.renderTail(added);
247
+ }
248
+ /**
249
+ * Full reset: rewind the cursor to 0 and drop all fold state. The next
250
+ * `update` replays the whole current surface (bounded). Also the KD-5
251
+ * reset surface for emission-guard / immuneTurns latches (T5/T6 hook into
252
+ * the same session lifecycle).
253
+ */
254
+ reset() {
255
+ this.cursor = 0;
256
+ this.surface.length = 0;
257
+ this.messages.clear();
258
+ this.deliveredFingerprint = undefined;
259
+ this.droppedPrefix = false;
260
+ }
261
+ /**
262
+ * Seed the cursor to `length` (KD-5 seed-on-enable): skip existing history
263
+ * — the next update renders only events at/after `length` (no full-history
264
+ * replay, matching omp).
265
+ */
266
+ seedTo(length) {
267
+ if (!Number.isSafeInteger(length) || length < 0) {
268
+ throw new RangeError(`dsh-advisor: seedTo length must be a non-negative safe integer, got ${String(length)}`);
269
+ }
270
+ this.reset();
271
+ this.cursor = length;
272
+ }
273
+ /**
274
+ * Read-only predicate for the agentic reply-complete gate (KD-N4-5): does an
275
+ * unreviewed non-advisor `assistant/message` increment exist since the
276
+ * cursor? Scans the unconsumed log tail with the same derivation the
277
+ * renderer uses (an empty-content `assistant/message` derives no message, so
278
+ * it does not count) and excludes advisor-source messages (self-review
279
+ * guard, spec §6). NEVER mutates state — a blind `update()` here would
280
+ * pre-advance the cursor and lose the user prompt from the first
281
+ * standard-session turn/end delta, so the caller only calls `update()` when
282
+ * this returns true.
283
+ */
284
+ hasUnreviewedAssistant(events) {
285
+ for (let index = this.cursor; index < events.length; index++) {
286
+ const event = events[index];
287
+ if (event.type !== 'assistant/message')
288
+ continue;
289
+ const message = deriveEventMessage(event);
290
+ if (message !== null && !isAdvisorMessage(message))
291
+ return true;
292
+ }
293
+ return false;
294
+ }
295
+ /** Rebuild the fold from a full log (post-reset replay, bounded to `length`). */
296
+ rebuild(events, length) {
297
+ const folded = foldSurface(events.slice(0, length));
298
+ for (const seq of folded.nodes) {
299
+ const message = deriveEventMessage(events[seq]);
300
+ if (message === null || isAdvisorMessage(message))
301
+ continue;
302
+ this.surface.push(seq);
303
+ this.messages.set(seq, message);
304
+ }
305
+ if (this.maxDeltaMessages > 0 && this.surface.length > this.maxDeltaMessages) {
306
+ const dropped = this.surface.splice(0, this.surface.length - this.maxDeltaMessages);
307
+ for (const seq of dropped)
308
+ this.messages.delete(seq);
309
+ this.droppedPrefix = true;
310
+ }
311
+ }
312
+ /** Incrementally fold new events in `[start, end)` (guaranteed append-only) and return added messages. */
313
+ append(events, start, end) {
314
+ const added = [];
315
+ for (let index = start; index < end; index++) {
316
+ const event = events[index];
317
+ const message = deriveEventMessage(event);
318
+ if (message === null || isAdvisorMessage(message))
319
+ continue;
320
+ this.surface.push(event.seq);
321
+ this.messages.set(event.seq, message);
322
+ added.push(message);
323
+ if (this.maxDeltaMessages > 0 && this.surface.length > this.maxDeltaMessages) {
324
+ const removed = this.surface.shift();
325
+ this.messages.delete(removed);
326
+ this.droppedPrefix = true;
327
+ }
328
+ }
329
+ return added;
330
+ }
331
+ /** Render the newly appended messages (incremental delta). */
332
+ renderTail(added) {
333
+ if (this.maxDeltaMessages > 0 && added.length > this.maxDeltaMessages) {
334
+ return this.render(added.slice(-this.maxDeltaMessages), true);
335
+ }
336
+ return this.render(added, false);
337
+ }
338
+ /** Render the current surface in full (post-reset replay, bounded). */
339
+ renderSurface() {
340
+ const messages = [];
341
+ for (const seq of this.surface) {
342
+ const message = this.messages.get(seq);
343
+ if (message !== undefined)
344
+ messages.push(message);
345
+ }
346
+ return this.render(messages, this.droppedPrefix);
347
+ }
348
+ render(messages, omitted) {
349
+ if (messages.length === 0)
350
+ return undefined;
351
+ const lines = [SESSION_UPDATE_HEADING];
352
+ if (omitted)
353
+ lines.push(TRUNCATION_MARKER);
354
+ for (const message of messages)
355
+ lines.push(renderMessage(message));
356
+ return { markdown: lines.join('\n\n'), willContinue: false };
357
+ }
358
+ }
359
+ /** `turn/end` reasons the advisor reviews (spec §4 — skip cut-short turns). */
360
+ const REVIEWABLE_TURN_END_KINDS = new Set(['completed', 'max-tokens', 'error']);
361
+ /** True when a `turn/end` event carries a reviewable end reason. */
362
+ export function isReviewableTurnEnd(event) {
363
+ return event.type === 'turn/end' && REVIEWABLE_TURN_END_KINDS.has(event.data.reason.kind);
364
+ }
365
+ /**
366
+ * True when an event is a human-input arrival — the trigger of the agentic
367
+ * reply-complete gate (KD-N4-5).
368
+ *
369
+ * - `user/message` with `source.kind === 'user'` — the primary signal: a
370
+ * direct human prompt (the queued message claimed for a step).
371
+ * - `agent/inbox/spliced` — the fallback: inbox-spliced input commits as
372
+ * this log-only event first and may never re-emit as `user/message`
373
+ * (the merged `SessionEventMap` entry comes from the dsh-agent peer, per
374
+ * the `compact/*` precedent). Payload-discriminated (C-1 fix): the event
375
+ * only triggers when `inserted` is non-empty and carries at least one
376
+ * message whose `source.kind === 'user'`. Every other inbox mutation is
377
+ * excluded — the advisor's OWN inject/steer deliveries (source.kind
378
+ * `advisor`), workspace-context sync (`workspace-instructions`),
379
+ * tool-result splicing (`tool`), and claim/clear splices (empty
380
+ * `inserted`) must not self-trigger the review gate.
381
+ *
382
+ * Synthetic/injected user-role messages (tool results, advisor notes,
383
+ * workspace context) carry other `source.kind` values and never trigger.
384
+ */
385
+ export function isHumanInputEvent(event) {
386
+ if (event.type === 'user/message')
387
+ return event.data.source.kind === 'user';
388
+ if (event.type === 'agent/inbox/spliced') {
389
+ return event.data.inserted.some((message) => message.source.kind === 'user');
390
+ }
391
+ return false;
392
+ }
393
+ /**
394
+ * One renderer per session id, driven by `session/event` tuples. Cordis-free,
395
+ * so the wiring logic is unit-testable; `index.ts` binds the cordis listeners
396
+ * into an instance and forwards `session.events` (the live log).
397
+ */
398
+ export class SessionTranscriptObserver {
399
+ options;
400
+ renderers = new Map();
401
+ /** seedTo lengths issued before a session's renderer existed (KD-5 enable). */
402
+ pendingSeeds = new Map();
403
+ /**
404
+ * Mode latch (KD-N4-5): sessions that have produced ANY `turn/end` event.
405
+ * Once a session emits `turn/end` it is a standard turn-driven session —
406
+ * the new agentic reply-complete gate sleeps for it (verbatim behavior,
407
+ * including spec §4 skip-aborted: a cut-short first turn's unreviewed
408
+ * increment must not be supplementarily reviewed). Agentic/harness
409
+ * sessions never emit `turn/end`, so they never latch and the new gate
410
+ * stays active. Per-session; cleared on dispose.
411
+ */
412
+ turnEndSessions = new Set();
413
+ /** Bounded delta window (KD-3); forwarded to every per-session renderer. */
414
+ maxDeltaMessages;
415
+ constructor(options) {
416
+ this.options = options;
417
+ this.maxDeltaMessages = options.maxDeltaMessages;
418
+ }
419
+ /**
420
+ * Update the bounded delta window (live config — settings onChange, plan
421
+ * dsh-advisor-settings-n2 T1): the observer default AND every live
422
+ * per-session renderer, so existing sessions pick up the new bound without
423
+ * losing their fold state.
424
+ */
425
+ setMaxDeltaMessages(value) {
426
+ this.maxDeltaMessages = value;
427
+ for (const renderer of this.renderers.values())
428
+ renderer.setMaxDeltaMessages(value);
429
+ }
430
+ /**
431
+ * Feed one session event (mirroring the cordis `session/event` listener:
432
+ * `(session, event)` — `events` is the session's live log, `event` the
433
+ * appended event). Renders (and emits via `onDelta`) on either trigger:
434
+ * a stepped `turn/end` with a reviewable reason (standard sessions), or a
435
+ * human-input arrival with an unreviewed assistant increment (agentic
436
+ * sessions — the reply-complete gate, KD-N4-5). The mode latch keeps the
437
+ * second gate dormant for any session that emits `turn/end`.
438
+ */
439
+ handleEvent(sessionId, events, event) {
440
+ // KD-5 reset surface: a rewrite event (compact/*, non-append surface op)
441
+ // clears the delivery immuneTurns latch immediately (T6) — before the turn
442
+ // gate, since a rewrite can arrive outside a turn/end.
443
+ if (isRewriteEvent(event))
444
+ this.options.onRewrite?.(sessionId);
445
+ // Mode latch: ANY turn/end marks the session as standard turn-driven. Set
446
+ // before the reviewable check — a non-reviewable (aborted/blocked) end
447
+ // still latches, so the new gate never supplementarily reviews a cut-short
448
+ // round (spec §4).
449
+ if (event.type === 'turn/end')
450
+ this.turnEndSessions.add(sessionId);
451
+ if (isReviewableTurnEnd(event)) {
452
+ // Stepped-turn gate: the arriving turn/end must be the latest closed turn
453
+ // that entered at least one model step (dsh semantics — no-step turns from
454
+ // rejection / empty input / cancellation are not reviewed).
455
+ const latest = findLastMessageTurnEnd(events);
456
+ if (latest === undefined || latest.seq !== event.seq)
457
+ return;
458
+ // One completed stepped primary turn — the delivery module (T6) counts
459
+ // these to decrement its immuneTurns cooldown. Fires before the render so
460
+ // the note produced by this very turn routes with the decremented value.
461
+ this.options.onSteppedTurnEnd?.(sessionId);
462
+ const delta = this.rendererFor(sessionId).update(events);
463
+ if (delta !== undefined)
464
+ this.options.onDelta(sessionId, delta);
465
+ return;
466
+ }
467
+ // KD-N4-5 reply-complete gate (agentic sessions, no turn/end): fire only
468
+ // on human-input arrival for a session that never latched as standard.
469
+ if (this.turnEndSessions.has(sessionId))
470
+ return;
471
+ if (!isHumanInputEvent(event))
472
+ return;
473
+ const renderer = this.rendererFor(sessionId);
474
+ // Read-only predicate — never advances the cursor on a miss: the first
475
+ // user input of a session must not trigger nor advance (a blind update()
476
+ // would pre-advance the cursor and lose the user prompt from the first
477
+ // standard-session turn/end delta).
478
+ if (!renderer.hasUnreviewedAssistant(events))
479
+ return;
480
+ // One completed reply round — the immuneTurns countdown (T6) fires before
481
+ // the render, same ordering as the turn/end path.
482
+ this.options.onSteppedTurnEnd?.(sessionId);
483
+ // Append-type trigger: the arriving input opens the next round — exclude
484
+ // the trigger event itself so it never enters the delta (the wiring
485
+ // guarantees `event` is the last log entry). skipLast does this WITHOUT
486
+ // the O(full-log) copy the previous `events.slice(0, -1)` paid on every
487
+ // review (qc3 F1). Rewrite-type trigger (compact summary replace): pass
488
+ // the full log so `update()` detects the rewrite and replays the
489
+ // post-rewrite surface (KD-5).
490
+ const delta = isRewriteEvent(event)
491
+ ? renderer.update(events)
492
+ : renderer.update(events, true);
493
+ if (delta !== undefined)
494
+ this.options.onDelta(sessionId, delta);
495
+ }
496
+ /** Lazy per-session renderer creation, shared by both trigger modes. */
497
+ rendererFor(sessionId) {
498
+ let renderer = this.renderers.get(sessionId);
499
+ if (renderer === undefined) {
500
+ renderer = new DeltaRenderer({ maxDeltaMessages: this.maxDeltaMessages });
501
+ const seed = this.pendingSeeds.get(sessionId);
502
+ if (seed !== undefined) {
503
+ renderer.seedTo(seed);
504
+ this.pendingSeeds.delete(sessionId);
505
+ }
506
+ this.renderers.set(sessionId, renderer);
507
+ }
508
+ return renderer;
509
+ }
510
+ /** Drop a session's renderer (wiring: `session/disposed` / `agent/disposed`). */
511
+ disposeSession(sessionId) {
512
+ this.renderers.delete(sessionId);
513
+ this.pendingSeeds.delete(sessionId);
514
+ this.turnEndSessions.delete(sessionId);
515
+ }
516
+ /**
517
+ * KD-5 seed-on-enable: skip existing history for a session's renderer.
518
+ * Issued before the renderer exists (e.g. `/advisor on` before the session
519
+ * produced a stepped turn), the seed is remembered and applied on creation.
520
+ */
521
+ seedTo(sessionId, length) {
522
+ const renderer = this.renderers.get(sessionId);
523
+ if (renderer === undefined) {
524
+ this.pendingSeeds.set(sessionId, length);
525
+ return;
526
+ }
527
+ renderer.seedTo(length);
528
+ }
529
+ }
530
+ //# sourceMappingURL=transcript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "dsh-advisor",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "dsh plugin bundle porting the omp advisor subsystem: a per-session reviewer model that observes the primary transcript and injects severity-ranked advice (nit/concern/blocker).",
6
+ "keywords": [
7
+ "dsh",
8
+ "dsh-plugin"
9
+ ],
10
+ "main": "./lib/index.js",
11
+ "types": "./lib/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./lib/index.d.ts",
15
+ "default": "./lib/index.js"
16
+ },
17
+ "./client": {
18
+ "types": "./lib/client.d.ts",
19
+ "default": "./lib/client.js"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "lib",
25
+ "cordis.patch.yml",
26
+ "scripts"
27
+ ],
28
+ "scripts": {
29
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.client.json --noEmit && tsc -p tsconfig.spec.json --noEmit",
30
+ "build": "tsc -p tsconfig.build.json && node scripts/build-client.mjs",
31
+ "prepare": "pnpm build",
32
+ "prepack": "pnpm build",
33
+ "test": "vitest run"
34
+ },
35
+ "dsh": {
36
+ "bundle": {
37
+ "patch": "./cordis.patch.yml"
38
+ },
39
+ "client": {
40
+ "inject": [
41
+ "@deepseek-ai/dsh-client-runtime",
42
+ "@deepseek-ai/dsh-client-ui-settings-plugins",
43
+ "@deepseek-ai/dsh-client-locale"
44
+ ],
45
+ "platform": "web"
46
+ }
47
+ },
48
+ "peerDependencies": {
49
+ "@deepseek-ai/cordis": "^4.0.1",
50
+ "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
51
+ "@deepseek-ai/dsh-api-gateway": "^0.1.0-rc.6",
52
+ "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
53
+ "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
54
+ "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
55
+ "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6",
56
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6",
57
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
58
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
59
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
60
+ "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6",
61
+ "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
62
+ "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
63
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
64
+ "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
65
+ "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6",
66
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6",
67
+ "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.6",
68
+ "react": "^18.2.0",
69
+ "schemastery": "^3.18.0"
70
+ },
71
+ "devDependencies": {
72
+ "@testing-library/dom": "^10.4.1",
73
+ "@testing-library/react": "^16.3.2",
74
+ "@types/node": "^26.2.0",
75
+ "@types/react": "~18.3.1",
76
+ "@types/react-dom": "~18.3.7",
77
+ "esbuild": "^0.28.2",
78
+ "jsdom": "29.1.1",
79
+ "lightningcss": "^1.33.0",
80
+ "react": "^18.3.1",
81
+ "react-dom": "^18.3.1",
82
+ "schemastery": "^3.18.0",
83
+ "typescript": "^5.6.0",
84
+ "vitest": "^3.0.0"
85
+ },
86
+ "engines": {
87
+ "node": "^22.19 || >=24"
88
+ },
89
+ "license": "MIT"
90
+ }