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.
- package/LICENSE +21 -0
- package/README.i18n.yaml +7 -0
- package/README.md +303 -0
- package/README.zh.md +166 -0
- package/cordis.patch.yml +6 -0
- package/lib/advisor-runtime.d.ts +242 -0
- package/lib/advisor-runtime.js +662 -0
- package/lib/advisor-runtime.js.map +1 -0
- package/lib/client/advisor-card.d.ts +90 -0
- package/lib/client/advisor-store.d.ts +310 -0
- package/lib/client/index.d.ts +39 -0
- package/lib/client/locales.d.ts +40 -0
- package/lib/client.d.ts +1 -0
- package/lib/client.js +840 -0
- package/lib/commands.d.ts +136 -0
- package/lib/commands.js +185 -0
- package/lib/commands.js.map +1 -0
- package/lib/config.d.ts +74 -0
- package/lib/config.js +93 -0
- package/lib/config.js.map +1 -0
- package/lib/delivery.d.ts +129 -0
- package/lib/delivery.js +169 -0
- package/lib/delivery.js.map +1 -0
- package/lib/emission-guard.d.ts +99 -0
- package/lib/emission-guard.js +155 -0
- package/lib/emission-guard.js.map +1 -0
- package/lib/gateway.d.ts +116 -0
- package/lib/gateway.js +214 -0
- package/lib/gateway.js.map +1 -0
- package/lib/index.d.ts +48 -0
- package/lib/index.js +485 -0
- package/lib/index.js.map +1 -0
- package/lib/kinds.d.ts +38 -0
- package/lib/kinds.js +24 -0
- package/lib/kinds.js.map +1 -0
- package/lib/prompts.d.ts +22 -0
- package/lib/prompts.js +38 -0
- package/lib/prompts.js.map +1 -0
- package/lib/settings.d.ts +96 -0
- package/lib/settings.js +141 -0
- package/lib/settings.js.map +1 -0
- package/lib/transcript.d.ts +257 -0
- package/lib/transcript.js +530 -0
- package/lib/transcript.js.map +1 -0
- package/package.json +90 -0
- 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
|
+
}
|