dsh-advisor 0.4.1 → 0.5.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.i18n.yaml +2 -2
- package/README.md +31 -22
- package/README.zh.md +31 -22
- package/lib/client/advisor-card.d.ts +18 -14
- package/lib/client/advisor-session.d.ts +75 -0
- package/lib/client/advisor-store.d.ts +131 -0
- package/lib/client/index.d.ts +18 -13
- package/lib/client/locales.d.ts +15 -0
- package/lib/client.js +375 -14
- package/lib/commands.d.ts +220 -27
- package/lib/commands.js +260 -34
- package/lib/commands.js.map +1 -1
- package/lib/config.d.ts +74 -20
- package/lib/config.js +74 -20
- package/lib/config.js.map +1 -1
- package/lib/delivery.d.ts +9 -9
- package/lib/delivery.js +10 -12
- package/lib/delivery.js.map +1 -1
- package/lib/gateway.d.ts +139 -24
- package/lib/gateway.js +138 -27
- package/lib/gateway.js.map +1 -1
- package/lib/index.d.ts +5 -5
- package/lib/index.js +483 -82
- package/lib/index.js.map +1 -1
- package/lib/kinds.d.ts +79 -51
- package/lib/kinds.js +60 -43
- package/lib/kinds.js.map +1 -1
- package/lib/settings.d.ts +56 -86
- package/lib/settings.js +48 -91
- package/lib/settings.js.map +1 -1
- package/lib/transcript.d.ts +11 -9
- package/lib/transcript.js +25 -16
- package/lib/transcript.js.map +1 -1
- package/lib/tui-settings.d.ts +10 -10
- package/lib/tui-settings.js +10 -10
- package/lib/tui-settings.js.map +1 -1
- package/lib/tui.js +39 -5
- package/lib/tui.js.map +1 -1
- package/package.json +24 -23
package/lib/commands.d.ts
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* T7 — slash commands (spec §2 S5, §6 status surface, §8.5 KD-5 seed-on-enable
|
|
2
|
+
* T7 — slash commands (spec §2 S5, §6 status surface, §8.5 KD-5 seed-on-enable,
|
|
3
|
+
* §5.3 session model override).
|
|
3
4
|
*
|
|
4
5
|
* One `/advisor` command is registered (through {@link registerAdvisorCommands})
|
|
5
|
-
* with
|
|
6
|
+
* with these forms:
|
|
6
7
|
*
|
|
7
8
|
* - `/advisor` — toggle the per-session override (on ↔ off);
|
|
8
9
|
* - `/advisor on` — enable the advisor for this session;
|
|
9
10
|
* - `/advisor off` — disable the advisor for this session;
|
|
10
11
|
* - `/advisor status` — report the per-session status surface;
|
|
11
|
-
* - `/advisor config` — show the composed advisor config (
|
|
12
|
+
* - `/advisor config` — show the composed advisor config (global defaults);
|
|
13
|
+
* - `/advisor model` — show the effective reviewer route + source;
|
|
14
|
+
* - `/advisor model set <provider> <model>` — pin an atomic pair for the
|
|
15
|
+
* invoking session only (validated via `resolveModelInfo`, 60 s, no retry);
|
|
16
|
+
* - `/advisor model reset` — re-inherit the current global defaults;
|
|
12
17
|
* - anything else — usage text.
|
|
13
18
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* the
|
|
19
|
+
* All forms are **session-scoped and ephemeral**: they drive per-session
|
|
20
|
+
* overrides ({@link AdvisorSessionOverrides} — the enable flag and the
|
|
21
|
+
* runtime-only atomic model pair, fenced by per-session generations) that the
|
|
22
|
+
* runtime gate and the effective resolver consult, so no command ever touches
|
|
23
|
+
* the persisted config (spec §4 mapping, §5.3 — matches omp `/advisor`
|
|
24
|
+
* semantics). Enabling a session whose effective route has no complete pair
|
|
25
|
+
* starts no model call: the S4 explicit gate (spec §5.2) applies AFTER session
|
|
26
|
+
* resolution, and the status/on text explains the disabled-with-reason.
|
|
21
27
|
*
|
|
22
28
|
* The module is cordis-free (pure parse + render + registration contract), so
|
|
23
29
|
* it is unit-testable with a fake command registry and a fake controller;
|
|
@@ -28,6 +34,7 @@
|
|
|
28
34
|
* @module dsh-advisor/commands
|
|
29
35
|
*/
|
|
30
36
|
import type { CommandDefinition } from '@deepseek-ai/dsh-commands';
|
|
37
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
31
38
|
import type { AdvisorRuntimeStatus } from './advisor-runtime.js';
|
|
32
39
|
/** The parsed form of the exact text following `/advisor`. */
|
|
33
40
|
export type AdvisorCommand = {
|
|
@@ -40,9 +47,64 @@ export type AdvisorCommand = {
|
|
|
40
47
|
readonly kind: 'status';
|
|
41
48
|
} | {
|
|
42
49
|
readonly kind: 'config';
|
|
50
|
+
} | {
|
|
51
|
+
readonly kind: 'model';
|
|
52
|
+
readonly sub: AdvisorModelCommand;
|
|
53
|
+
} | {
|
|
54
|
+
readonly kind: 'usage';
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* The parsed form of the text following `/advisor model` (spec §5.3 B1
|
|
58
|
+
* surface): bare → show, `set <provider> <model>` → set (parsed by
|
|
59
|
+
* {@link parseModelSetArgs}), `reset` → reset, anything else → model usage.
|
|
60
|
+
*/
|
|
61
|
+
export type AdvisorModelCommand = {
|
|
62
|
+
readonly kind: 'show';
|
|
63
|
+
} | {
|
|
64
|
+
readonly kind: 'set';
|
|
65
|
+
readonly args: string;
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: 'reset';
|
|
43
68
|
} | {
|
|
44
69
|
readonly kind: 'usage';
|
|
45
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Parse the text following `/advisor model`. `set` keeps its RAW remainder —
|
|
73
|
+
* the atomic-pair validation ({@link parseModelSetArgs}) owns it, because the
|
|
74
|
+
* set flow reports a precise rejection reason in the command reply.
|
|
75
|
+
*/
|
|
76
|
+
export declare function parseAdvisorModelCommand(rawInput: string): AdvisorModelCommand;
|
|
77
|
+
/**
|
|
78
|
+
* The result of parsing `/advisor model set` arguments into the atomic pair
|
|
79
|
+
* (spec §5.3 pair validation).
|
|
80
|
+
*/
|
|
81
|
+
export type ModelSetArgs = {
|
|
82
|
+
readonly ok: true;
|
|
83
|
+
readonly provider: string;
|
|
84
|
+
readonly model: string;
|
|
85
|
+
} | {
|
|
86
|
+
readonly ok: false;
|
|
87
|
+
readonly reason: string;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Validate one structured `{provider, model}` pair (spec §5.3 pair validation):
|
|
91
|
+
* both values must be strings that are non-empty after outer trim, with no
|
|
92
|
+
* whitespace INSIDE either identifier (the same rules `parseModelSetArgs`
|
|
93
|
+
* enforces for the CLI form — one validation source shared by the command face
|
|
94
|
+
* and the web gateway face, so the two surfaces can never diverge). Outer
|
|
95
|
+
* whitespace is trimmed; case is retained; model ids containing `/` are fine
|
|
96
|
+
* (`/` is not whitespace). Never throws — every rejection carries a
|
|
97
|
+
* user-facing reason.
|
|
98
|
+
*/
|
|
99
|
+
export declare function parseModelPair(provider: unknown, model: unknown): ModelSetArgs;
|
|
100
|
+
/**
|
|
101
|
+
* Validate `/advisor model set <provider> <model>` arguments (spec §5.3):
|
|
102
|
+
* exactly two arguments; outer whitespace trimmed; case retained; blank or
|
|
103
|
+
* partial pairs, extra fields (a third argument), and whitespace-containing
|
|
104
|
+
* identifiers rejected. Separate args are what allow model ids containing
|
|
105
|
+
* `/`. Never throws — every rejection carries a user-facing reason.
|
|
106
|
+
*/
|
|
107
|
+
export declare function parseModelSetArgs(rawArgs: string): ModelSetArgs;
|
|
46
108
|
/**
|
|
47
109
|
* Parse the text following `/advisor` (the dsh `parseCommand` split already
|
|
48
110
|
* yields `rawInput` including the separator whitespace, e.g. `' on'` for
|
|
@@ -51,15 +113,45 @@ export type AdvisorCommand = {
|
|
|
51
113
|
*/
|
|
52
114
|
export declare function parseAdvisorCommand(rawInput: string): AdvisorCommand;
|
|
53
115
|
/**
|
|
54
|
-
* The
|
|
55
|
-
* `
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
116
|
+
* The runtime-only reviewer model override for one session (spec §5.3) — an
|
|
117
|
+
* **atomic** `{ provider, model }` pair. It never merges with the global
|
|
118
|
+
* pair (no half-pairs) and is never persisted: it lives in memory for the
|
|
119
|
+
* live-session lifetime and is cleared by reset, dispose, owner teardown,
|
|
120
|
+
* cold resume, or restart.
|
|
121
|
+
*/
|
|
122
|
+
export interface AdvisorModelPair {
|
|
123
|
+
readonly provider: string;
|
|
124
|
+
readonly model: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Where a session's effective reviewer route comes from (spec §5.3):
|
|
128
|
+
* `session` = a pinned `AdvisorModelPair`, `global` = the composed global
|
|
129
|
+
* advisor pair.
|
|
130
|
+
*/
|
|
131
|
+
export type AdvisorModelSource = 'session' | 'global';
|
|
132
|
+
/**
|
|
133
|
+
* The per-session overrides consulted by the runtime gate and the effective
|
|
134
|
+
* resolver (`src/index.ts`):
|
|
135
|
+
*
|
|
136
|
+
* - enable: `override ?? config.enabled` (`/advisor on|off|toggle`);
|
|
137
|
+
* - model: the complete session pair ?? the composed global pair — the pair
|
|
138
|
+
* is atomic, so the two levels are never merged (spec §5.3);
|
|
139
|
+
* - generation: a per-session counter that fences async model work — a newer
|
|
140
|
+
* set/reset supersedes unresolved older work, and dispose/owner teardown
|
|
141
|
+
* (which wipe the counter) can never be undone by a delayed completion.
|
|
142
|
+
*
|
|
143
|
+
* Nothing here touches the persisted config. All maps are keyed by session id
|
|
144
|
+
* and hold only LIVE sessions' state: `clear` runs on `agent/disposed` /
|
|
145
|
+
* `session/disposed`, `clearModel` runs on reset (an emptied entry is
|
|
146
|
+
* removed), and `disposeAll` runs on owner teardown — state stays
|
|
147
|
+
* O(live overrides), with no historical SessionId accumulation and no
|
|
148
|
+
* TTL/GC job.
|
|
59
149
|
*/
|
|
60
150
|
export declare class AdvisorSessionOverrides {
|
|
61
151
|
private configEnabled;
|
|
62
|
-
private readonly
|
|
152
|
+
private readonly enables;
|
|
153
|
+
private readonly models;
|
|
154
|
+
private readonly generations;
|
|
63
155
|
constructor(configEnabled: boolean);
|
|
64
156
|
/** Effective switch for one session: `override ?? config.enabled`. */
|
|
65
157
|
effective(sessionId: string): boolean;
|
|
@@ -70,10 +162,41 @@ export declare class AdvisorSessionOverrides {
|
|
|
70
162
|
* takes effect for new sessions without touching the override mechanism.
|
|
71
163
|
*/
|
|
72
164
|
setConfigEnabled(enabled: boolean): void;
|
|
73
|
-
/** Set the override for one session. */
|
|
165
|
+
/** Set the enable override for one session. */
|
|
74
166
|
set(sessionId: string, enabled: boolean): void;
|
|
75
|
-
/**
|
|
167
|
+
/** The session's pinned model pair, or `undefined` when it inherits. */
|
|
168
|
+
model(sessionId: string): AdvisorModelPair | undefined;
|
|
169
|
+
/** Commit the (already validated) atomic pair for one session. */
|
|
170
|
+
setModel(sessionId: string, pair: AdvisorModelPair): void;
|
|
171
|
+
/**
|
|
172
|
+
* Remove a session's model pin (reset-to-inherit). @returns `true` when a
|
|
173
|
+
* pin was actually removed — `false` means the session was already
|
|
174
|
+
* inheriting (a reset no-op).
|
|
175
|
+
*/
|
|
176
|
+
clearModel(sessionId: string): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Bump and return the session's model-work generation — the fence token an
|
|
179
|
+
* async validation captures; any later `beginModelGeneration` (a newer
|
|
180
|
+
* set/reset) or any state wipe makes the captured value stale.
|
|
181
|
+
*/
|
|
182
|
+
beginModelGeneration(sessionId: string): number;
|
|
183
|
+
/** The session's current model-work generation (0 before the first). */
|
|
184
|
+
modelGeneration(sessionId: string): number;
|
|
185
|
+
/** Sessions holding ANY per-session override state (enable and/or pair). */
|
|
186
|
+
overrideSessionIds(): IterableIterator<string>;
|
|
187
|
+
/**
|
|
188
|
+
* Drop ALL per-session state for one session (enable + pair + generation) —
|
|
189
|
+
* the `agent/disposed` / `session/disposed` cleanup. Wiping the generation
|
|
190
|
+
* invalidates any in-flight validation for the session (captured values are
|
|
191
|
+
* ≥ 1 and can never again match the post-clear default 0).
|
|
192
|
+
*/
|
|
76
193
|
clear(sessionId: string): void;
|
|
194
|
+
/**
|
|
195
|
+
* Owner teardown: wipe every session's state. Pending validations for any
|
|
196
|
+
* session become stale exactly like a per-session `clear` — a delayed
|
|
197
|
+
* completion can never commit after the owner is gone.
|
|
198
|
+
*/
|
|
199
|
+
disposeAll(): void;
|
|
77
200
|
}
|
|
78
201
|
/**
|
|
79
202
|
* Per-session status snapshot consumed by `/advisor status`. Built by the
|
|
@@ -93,6 +216,12 @@ export interface AdvisorSessionStatus {
|
|
|
93
216
|
readonly provider?: string;
|
|
94
217
|
/** Configured model id (shown even while disabled — spec §5.2). */
|
|
95
218
|
readonly model?: string;
|
|
219
|
+
/**
|
|
220
|
+
* Where the reported route comes from (spec §5.3) — present iff
|
|
221
|
+
* `provider`/`model` are: `session` = the session's pinned pair,
|
|
222
|
+
* `global` = the composed global advisor pair.
|
|
223
|
+
*/
|
|
224
|
+
readonly modelSource?: AdvisorModelSource;
|
|
96
225
|
/** The session's runtime status; `disabled` when no runtime exists. */
|
|
97
226
|
readonly runtimeStatus: AdvisorRuntimeStatus;
|
|
98
227
|
/** Deltas waiting to be drained (bounded backlog, spec §6). */
|
|
@@ -106,13 +235,59 @@ export interface AdvisorSessionStatus {
|
|
|
106
235
|
* the pending count, and the last accepted-note activity (ISO, or `never`).
|
|
107
236
|
*/
|
|
108
237
|
export declare function advisorStatusText(status: AdvisorSessionStatus): string;
|
|
238
|
+
/** Validation deadline for one `/advisor model set` lookup (60 s — matches
|
|
239
|
+
* the runtime's whole-call deadline default, `src/advisor-runtime.ts`). */
|
|
240
|
+
export declare const ADVISOR_MODEL_VALIDATION_TIMEOUT_MS = 60000;
|
|
241
|
+
/** The effective reviewer route for one session (spec §5.3). */
|
|
242
|
+
export interface AdvisorModelRoute {
|
|
243
|
+
readonly provider?: string;
|
|
244
|
+
readonly model?: string;
|
|
245
|
+
/** `session` when the effective pair is the session's pin, else `global`. */
|
|
246
|
+
readonly source: AdvisorModelSource;
|
|
247
|
+
}
|
|
248
|
+
/** Outcome of one `/advisor model set` attempt (spec §5.3 validation + fencing). */
|
|
249
|
+
export type AdvisorSetModelOutcome = {
|
|
250
|
+
readonly kind: 'committed';
|
|
251
|
+
readonly status: AdvisorSessionStatus;
|
|
252
|
+
} | {
|
|
253
|
+
readonly kind: 'unchanged';
|
|
254
|
+
readonly status: AdvisorSessionStatus;
|
|
255
|
+
} | {
|
|
256
|
+
readonly kind: 'rejected';
|
|
257
|
+
readonly reason: string;
|
|
258
|
+
} | {
|
|
259
|
+
readonly kind: 'failed';
|
|
260
|
+
readonly reason: string;
|
|
261
|
+
} | {
|
|
262
|
+
readonly kind: 'cancelled';
|
|
263
|
+
} | {
|
|
264
|
+
readonly kind: 'superseded';
|
|
265
|
+
} | {
|
|
266
|
+
readonly kind: 'gone';
|
|
267
|
+
};
|
|
268
|
+
/** Outcome of one `/advisor model reset`. */
|
|
269
|
+
export type AdvisorResetModelOutcome = {
|
|
270
|
+
readonly kind: 'reset';
|
|
271
|
+
readonly status: AdvisorSessionStatus;
|
|
272
|
+
} | {
|
|
273
|
+
readonly kind: 'noop';
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* Render the `/advisor model` surface: the effective pair, its source, and
|
|
277
|
+
* the live-session lifetime (spec §5.3 — the reply must name the lifetime).
|
|
278
|
+
*/
|
|
279
|
+
export declare function advisorModelText(route: AdvisorModelRoute): string;
|
|
280
|
+
/** Render one `/advisor model set` outcome. */
|
|
281
|
+
export declare function modelSetText(outcome: AdvisorSetModelOutcome): string;
|
|
282
|
+
/** Render one `/advisor model reset` outcome. */
|
|
283
|
+
export declare function modelResetText(outcome: AdvisorResetModelOutcome): string;
|
|
109
284
|
/**
|
|
110
285
|
* Composed-config surface consumed by `/advisor config`. **Session-less by
|
|
111
286
|
* design**: the wiring builds it from the same resolved config the web card
|
|
112
|
-
* reads (`/api/advisor/get` —
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
287
|
+
* reads (`/api/advisor/get` — the live entry config, with the hard gate
|
|
288
|
+
* applied), so a per-session `/advisor off` override can never misreport the
|
|
289
|
+
* persisted config. Runtime state stays owned by the status surface
|
|
290
|
+
* (`AdvisorSessionStatus`); config and status are separate.
|
|
116
291
|
*/
|
|
117
292
|
export interface AdvisorComposedConfig {
|
|
118
293
|
/** Config-level composed switch — NOT the per-session override. */
|
|
@@ -141,8 +316,7 @@ export interface AdvisorComposedConfig {
|
|
|
141
316
|
* dsh-advisor-tui-settings-n9 T2). An environment signal, never derived
|
|
142
317
|
* from the per-session override; it does not change the resolved-config
|
|
143
318
|
* read. When true the hint lists the TUI `/settings` screen as a write
|
|
144
|
-
* path; when false the
|
|
145
|
-
* shown unchanged.
|
|
319
|
+
* path; when false the profile patch layer hint is shown unchanged.
|
|
146
320
|
*/
|
|
147
321
|
readonly tuiSettingsAvailable: boolean;
|
|
148
322
|
}
|
|
@@ -157,9 +331,9 @@ export declare function summarizeSystemPrompt(prompt: string): string;
|
|
|
157
331
|
* Render the composed config surface. Mirrors the status renderer's minimal
|
|
158
332
|
* line style; the edit hint points at the operator edit paths — when the TUI
|
|
159
333
|
* `tuiSettingsSections` seam is mounted (dsh-tui ≥ v0.8.0) the TUI `/settings`
|
|
160
|
-
* Advisor section is listed FIRST, followed by the profile patch layer
|
|
161
|
-
*
|
|
162
|
-
* otherwise only the
|
|
334
|
+
* Advisor section is listed FIRST, followed by the profile patch layer
|
|
335
|
+
* (`cordis.patch.yml`, whose `advisor` plugin row carries the volatile live
|
|
336
|
+
* fields); otherwise only the file path.
|
|
163
337
|
*/
|
|
164
338
|
export declare function advisorConfigText(config: AdvisorComposedConfig): string;
|
|
165
339
|
/**
|
|
@@ -180,6 +354,23 @@ export interface AdvisorCommandController {
|
|
|
180
354
|
getStatus(sessionId: string): AdvisorSessionStatus;
|
|
181
355
|
/** Snapshot the composed config surface (session-less settings readback). */
|
|
182
356
|
getConfig(): AdvisorComposedConfig;
|
|
357
|
+
/** The session's effective reviewer route (pair + source — spec §5.3). */
|
|
358
|
+
getModelRoute(sessionId: string): AdvisorModelRoute;
|
|
359
|
+
/**
|
|
360
|
+
* Validate and commit an atomic pair for the INVOKING session (spec §5.3):
|
|
361
|
+
* resolve through the LLM service before commit (60 s deadline, fused with
|
|
362
|
+
* `signal`, cancellable, NO automatic retry — failure leaves the previous
|
|
363
|
+
* selection untouched), fenced by the per-session generation. Never toggles
|
|
364
|
+
* the enable override; never starts a generation call.
|
|
365
|
+
*/
|
|
366
|
+
setModel(sessionId: string, provider: string, model: string, agent: Agent, signal?: AbortSignal): Promise<AdvisorSetModelOutcome>;
|
|
367
|
+
/**
|
|
368
|
+
* Drop the session's pin and re-inherit the CURRENT global defaults (never
|
|
369
|
+
* touches the enable override). Synchronous — no validation needed.
|
|
370
|
+
* @param sessionLength - current transcript length, used for the re-seed
|
|
371
|
+
* when the effective route actually changes.
|
|
372
|
+
*/
|
|
373
|
+
resetModel(sessionId: string, sessionLength?: number): AdvisorResetModelOutcome;
|
|
183
374
|
}
|
|
184
375
|
/** Minimal command registry surface (satisfied by the dsh `CommandService`). */
|
|
185
376
|
export interface AdvisorCommandRegistry {
|
|
@@ -187,6 +378,8 @@ export interface AdvisorCommandRegistry {
|
|
|
187
378
|
}
|
|
188
379
|
/** Usage text for an unknown `/advisor` subcommand. */
|
|
189
380
|
export declare const USAGE: string;
|
|
381
|
+
/** Usage text for an unknown `/advisor model` subcommand. */
|
|
382
|
+
export declare const MODEL_USAGE: string;
|
|
190
383
|
/**
|
|
191
384
|
* Register the `/advisor` command with a command registry (the dsh
|
|
192
385
|
* `CommandService`, or a fake in tests). Called from the plugin's conditional
|