dsh-llm-fallbacks 0.3.0 → 0.3.2
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 +60 -24
- package/README.zh-CN.md +58 -22
- package/dist/client/FallbacksCard.d.ts +1 -1
- package/dist/client/GeneralFallbacksRow.d.ts +1 -1
- package/dist/client/index.js +165 -5
- package/dist/client/use-snapshot.d.ts +11 -0
- package/dist/commands.d.ts +120 -27
- package/dist/gateway.d.ts +17 -0
- package/dist/index.js +473 -12
- package/dist/selectors.d.ts +6 -3
- package/dist/tui-settings.d.ts +140 -0
- package/dist/tui.d.ts +5 -4
- package/package.json +26 -23
- package/scripts/build-client.ts +9 -9
package/dist/commands.d.ts
CHANGED
|
@@ -11,12 +11,17 @@
|
|
|
11
11
|
* the command is silently absent when no command registry is composed (no
|
|
12
12
|
* top-level inject pollution — advisor T1 fix).
|
|
13
13
|
*
|
|
14
|
-
* The
|
|
15
|
-
* reset, no pending-switch writes).
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
14
|
+
* The bare diagnostic and the config readback are **read-only**: they never
|
|
15
|
+
* mutate fallback state (no cooldown reset, no pending-switch writes). The
|
|
16
|
+
* `config revert-seed <role-id>` subcommand is the one write action (plan
|
|
17
|
+
* fallbacks-tui-settings Task 2, AC-3): it delegates to the controller's
|
|
18
|
+
* `revertSeed` (wired to the seeds service) and prints the outcome — a
|
|
19
|
+
* web-card action capability the settings seam cannot express. zh/en copy
|
|
20
|
+
* lives in this file — the client half's `src/client/locales.ts` is a
|
|
21
|
+
* separate client-side dictionary. The host carries no per-session locale
|
|
22
|
+
* signal (the `locale` service is client-side), so the wiring picks a
|
|
23
|
+
* deterministic default (`zh`, this repo's primary language); both
|
|
24
|
+
* dictionaries are unit-tested.
|
|
20
25
|
*
|
|
21
26
|
* @module dsh-llm-fallbacks/commands
|
|
22
27
|
*/
|
|
@@ -24,7 +29,8 @@ import type { CommandDefinition } from '@deepseek-ai/dsh-commands';
|
|
|
24
29
|
import { type FallbacksRole } from './config.ts';
|
|
25
30
|
import type { Origin } from './roles.ts';
|
|
26
31
|
import type { FallbacksSwitchEventData } from './events.ts';
|
|
27
|
-
import type {
|
|
32
|
+
import type { SeedRevertFailReason } from './seeds.ts';
|
|
33
|
+
import { type SlotRowConfig } from './time-slots.ts';
|
|
28
34
|
/** How many recent `fallbacks/switch` events `/fallbacks` shows (newest first). */
|
|
29
35
|
export declare const RECENT_SWITCHES_LIMIT = 5;
|
|
30
36
|
/** Minimal command registry surface (satisfied by the dsh `CommandService`). */
|
|
@@ -90,15 +96,40 @@ export interface FallbacksCommandSnapshot {
|
|
|
90
96
|
* entities carry id/persona/chain/fallback (NO per-role `model`;
|
|
91
97
|
* `provider`/`model` live on `roles.rules`), so the readback line is id +
|
|
92
98
|
* chain count, never a rules dump.
|
|
99
|
+
*
|
|
100
|
+
* Enriched readback (plan fallbacks-tui-settings Task 2, AC-4): timeSlots /
|
|
101
|
+
* tz / roles.rules join the summary so TUI operators can verify `/settings`
|
|
102
|
+
* edits. One summarized time-slot row: preset rows carry `{ preset,
|
|
103
|
+
* chainCount }` (windows are frozen code constants in {@link PRESETS} and
|
|
104
|
+
* never stored on the row — the render resolves the window text from
|
|
105
|
+
* PRESETS); custom rows carry `{ start, end, chainCount }`. Rules rows carry
|
|
106
|
+
* `{ provider, model, role }` — an omitted provider/model (wildcard match at
|
|
107
|
+
* runtime) is summarized as `''` and rendered as `*`.
|
|
93
108
|
*/
|
|
94
109
|
export interface FallbacksConfigSummary {
|
|
95
110
|
readonly enabled: boolean;
|
|
96
111
|
readonly triggerCodes: readonly string[];
|
|
97
112
|
readonly rootChain: readonly string[];
|
|
113
|
+
/** Summarized time-slot rows (preset rows carry `preset`, custom rows carry `start`/`end`; both may carry a day mask). */
|
|
114
|
+
readonly timeSlots: readonly {
|
|
115
|
+
preset?: string;
|
|
116
|
+
start?: string;
|
|
117
|
+
end?: string;
|
|
118
|
+
days?: readonly number[];
|
|
119
|
+
chainCount: number;
|
|
120
|
+
}[];
|
|
121
|
+
/** Config-level timezone for slot matching (default `Asia/Shanghai`). */
|
|
122
|
+
readonly tz: string;
|
|
98
123
|
readonly roles: readonly {
|
|
99
124
|
id: string;
|
|
100
125
|
chainCount: number;
|
|
101
126
|
}[];
|
|
127
|
+
/** Summarized role rules: provider/model patterns → declared role (or the built-in `'inherit'`). */
|
|
128
|
+
readonly rules: readonly {
|
|
129
|
+
provider: string;
|
|
130
|
+
model: string;
|
|
131
|
+
role: string;
|
|
132
|
+
}[];
|
|
102
133
|
readonly cooldownMs: number;
|
|
103
134
|
readonly revertPolicy: string;
|
|
104
135
|
readonly maxSwitchesPerStep: number;
|
|
@@ -122,6 +153,23 @@ export interface FallbacksCommandController {
|
|
|
122
153
|
* same live config source the runtime reads. Never mutates state.
|
|
123
154
|
*/
|
|
124
155
|
getConfig(): FallbacksConfigSummary;
|
|
156
|
+
/**
|
|
157
|
+
* Revert one role's persona to its CURRENT declared seed default (AC-3).
|
|
158
|
+
* Surfaces the outcome as VALUES, not copy (qc1 F-003 / qc2 F-006 / qc3
|
|
159
|
+
* F-003): `ok: true` when reverted; `ok: false` with the
|
|
160
|
+
* {@link SeedRevertFailReason} code explaining why not (not a seeded role
|
|
161
|
+
* / role row absent). The command handler localizes the code per its
|
|
162
|
+
* registration locale — the controller never pre-localizes. A
|
|
163
|
+
* settings-write failure propagates loudly as a rejected promise (the
|
|
164
|
+
* same contract as the seeds service — never swallowed into an
|
|
165
|
+
* `ok: false`); the handler maps it to a structured error. Implemented by
|
|
166
|
+
* the wiring against the per-apply seed manager
|
|
167
|
+
* (`seeds.revert(roleId, seedsIo)`), not the typert gateway.
|
|
168
|
+
*/
|
|
169
|
+
revertSeed(roleId: string): Promise<{
|
|
170
|
+
ok: boolean;
|
|
171
|
+
reason?: SeedRevertFailReason;
|
|
172
|
+
}>;
|
|
125
173
|
}
|
|
126
174
|
/** zh/en dictionaries for the `/fallbacks` output. */
|
|
127
175
|
export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
@@ -129,7 +177,8 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
129
177
|
readonly title: "当前会话 fallback 诊断(只读)";
|
|
130
178
|
readonly description: "查看当前会话的降级链、最近降级切换与冷却状态(只读)";
|
|
131
179
|
readonly usageConfig: "查看组合后的 fallbacks 配置(设置回读)";
|
|
132
|
-
readonly
|
|
180
|
+
readonly usageRevertSeed: "将角色的 persona 还原为已声明的 Seed 默认";
|
|
181
|
+
readonly usage: " /fallbacks config 查看组合后的 fallbacks 配置(设置回读)\n /fallbacks config revert-seed <role-id> 将角色的 persona 还原为已声明的 Seed 默认";
|
|
133
182
|
readonly origin: "会话来源";
|
|
134
183
|
readonly role: "角色";
|
|
135
184
|
readonly chain: "链";
|
|
@@ -153,22 +202,37 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
153
202
|
readonly configTriggerCodes: "触发码";
|
|
154
203
|
readonly configRootChain: "根链";
|
|
155
204
|
readonly configEmpty: "(空)";
|
|
205
|
+
readonly configTimeSlots: "分时槽";
|
|
206
|
+
readonly configSlotPresetItem: "{preset}(chain: {n}, window {window})";
|
|
207
|
+
readonly configSlotPresetBare: "{preset}(chain: {n})";
|
|
208
|
+
readonly configSlotCustomItem: "custom {start}-{end}(chain: {n})";
|
|
209
|
+
readonly configTz: "时区";
|
|
156
210
|
readonly configRoles: "角色";
|
|
157
211
|
readonly configRoleItem: "{id}(chain: {n})";
|
|
212
|
+
readonly configRules: "角色规则";
|
|
158
213
|
readonly configCooldown: "冷却";
|
|
159
214
|
readonly configRevert: "回主策略";
|
|
160
215
|
readonly configMaxSwitches: "单步最大切换";
|
|
161
216
|
readonly configAlwaysCap: "always 上限";
|
|
162
217
|
readonly configPresets: "预置";
|
|
163
218
|
readonly configRoleAutoMatch: "角色自动匹配";
|
|
164
|
-
readonly configEdit: "
|
|
165
|
-
readonly configEditHint: "TUI
|
|
219
|
+
readonly configEdit: "编辑:/settings(TUI 设置界面)或 ~/.dsh/profiles/<profile>/cordis.patch.yml(插件行)/ $DSH_HOME/settings.yaml(fallbacks: 分节)";
|
|
220
|
+
readonly configEditHint: "TUI 通过 /settings 修改配置;文件编辑仍然可用";
|
|
221
|
+
readonly revertSeedOk: "角色 {id} 已还原为 Seed 默认";
|
|
222
|
+
readonly revertSeedFail: "角色 {id} 未还原({reason})";
|
|
223
|
+
readonly revertSeedError: "角色 {id} 还原失败(设置写入失败)";
|
|
224
|
+
readonly revertSeedReason: {
|
|
225
|
+
readonly 'not-seeded': "未声明种子";
|
|
226
|
+
readonly 'row-absent': "角色行不存在";
|
|
227
|
+
readonly 'settings-unavailable': "设置通道不可用";
|
|
228
|
+
};
|
|
166
229
|
};
|
|
167
230
|
readonly en: {
|
|
168
231
|
readonly title: "Session fallback diagnostics (read-only)";
|
|
169
232
|
readonly description: "Inspect fallback chain, recent fallback switches, and cooldown for this session (read-only)";
|
|
170
233
|
readonly usageConfig: "show the composed fallbacks config (settings readback)";
|
|
171
|
-
readonly
|
|
234
|
+
readonly usageRevertSeed: "revert a role's persona to its declared seed default";
|
|
235
|
+
readonly usage: " /fallbacks config show the composed fallbacks config (settings readback)\n /fallbacks config revert-seed <role-id> revert a role's persona to its declared seed default";
|
|
172
236
|
readonly origin: "Session origin";
|
|
173
237
|
readonly role: "Role";
|
|
174
238
|
readonly chain: "Chain";
|
|
@@ -192,29 +256,53 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
192
256
|
readonly configTriggerCodes: "Trigger codes";
|
|
193
257
|
readonly configRootChain: "Root chain";
|
|
194
258
|
readonly configEmpty: "(empty)";
|
|
259
|
+
readonly configTimeSlots: "Time slots";
|
|
260
|
+
readonly configSlotPresetItem: "{preset} (chain: {n}, window {window})";
|
|
261
|
+
readonly configSlotPresetBare: "{preset} (chain: {n})";
|
|
262
|
+
readonly configSlotCustomItem: "custom {start}-{end} (chain: {n})";
|
|
263
|
+
readonly configTz: "TZ";
|
|
195
264
|
readonly configRoles: "Roles";
|
|
196
265
|
readonly configRoleItem: "{id} (chain: {n})";
|
|
266
|
+
readonly configRules: "Rules";
|
|
197
267
|
readonly configCooldown: "Cooldown";
|
|
198
268
|
readonly configRevert: "Revert";
|
|
199
269
|
readonly configMaxSwitches: "Max switches/step";
|
|
200
270
|
readonly configAlwaysCap: "Always-mode cap";
|
|
201
271
|
readonly configPresets: "Presets";
|
|
202
272
|
readonly configRoleAutoMatch: "Auto-match";
|
|
203
|
-
readonly configEdit: "Edit: ~/.dsh/profiles/<profile>/cordis.patch.yml (plugin row)
|
|
204
|
-
readonly configEditHint: "TUI
|
|
273
|
+
readonly configEdit: "Edit: /settings (TUI settings screen) or ~/.dsh/profiles/<profile>/cordis.patch.yml (plugin row) / $DSH_HOME/settings.yaml (fallbacks: section)";
|
|
274
|
+
readonly configEditHint: "TUI edits config via /settings; file editing still works";
|
|
275
|
+
readonly revertSeedOk: "role {id} reverted to its seed default";
|
|
276
|
+
readonly revertSeedFail: "role {id} not reverted ({reason})";
|
|
277
|
+
readonly revertSeedError: "role {id} revert failed (settings write failed)";
|
|
278
|
+
readonly revertSeedReason: {
|
|
279
|
+
readonly 'not-seeded': "not a seeded role";
|
|
280
|
+
readonly 'row-absent': "role row absent";
|
|
281
|
+
readonly 'settings-unavailable': "settings channel unavailable";
|
|
282
|
+
};
|
|
205
283
|
};
|
|
206
284
|
};
|
|
207
285
|
/** A locale id supported by {@link FALLBACKS_COMMAND_LOCALES}. */
|
|
208
286
|
export type FallbacksCommandLocale = keyof typeof FALLBACKS_COMMAND_LOCALES;
|
|
209
|
-
/** The `/fallbacks` subcommands: `'config'` (composed-config readback)
|
|
210
|
-
* `''` (
|
|
211
|
-
|
|
287
|
+
/** The `/fallbacks` subcommands: `'config'` (composed-config readback),
|
|
288
|
+
* `'revert-seed'` (persona revert action, requires a role id), or `''` (the
|
|
289
|
+
* bare session snapshot). */
|
|
290
|
+
export type FallbacksSubcommand = '' | 'config' | 'revert-seed';
|
|
291
|
+
/** One parsed subcommand invocation: the kind plus the optional role id
|
|
292
|
+
* carried by `revert-seed`. */
|
|
293
|
+
export interface FallbacksSubcommandParse {
|
|
294
|
+
readonly kind: FallbacksSubcommand;
|
|
295
|
+
/** The role id argument of `revert-seed` (present iff `kind === 'revert-seed'`). */
|
|
296
|
+
readonly arg?: string;
|
|
297
|
+
}
|
|
212
298
|
/**
|
|
213
299
|
* Map an invocation's rawInput to a subcommand: trimmed `'config'` →
|
|
214
|
-
* `'config'`;
|
|
215
|
-
*
|
|
300
|
+
* `{ kind: 'config' }`; `'config revert-seed <id>'` → `{ kind: 'revert-seed',
|
|
301
|
+
* arg: id }`; everything else (incl. empty, a missing id, or an unknown
|
|
302
|
+
* subcommand under `config`) → `{ kind: '' }` (bare snapshot). Lenient by
|
|
303
|
+
* design — unknown input keeps today's bare behavior, never errors.
|
|
216
304
|
*/
|
|
217
|
-
export declare function parseFallbacksSubcommand(rawInput: string):
|
|
305
|
+
export declare function parseFallbacksSubcommand(rawInput: string): FallbacksSubcommandParse;
|
|
218
306
|
/**
|
|
219
307
|
* The newest `limit` `fallbacks/switch` events from a session's raw event
|
|
220
308
|
* log, newest first. Unknown event shapes and malformed `fallbacks/switch`
|
|
@@ -248,18 +336,23 @@ export declare function resolveChainForDiagnostic(roles: readonly FallbacksRole[
|
|
|
248
336
|
readonly inherit: boolean;
|
|
249
337
|
};
|
|
250
338
|
/**
|
|
251
|
-
* Cap for
|
|
252
|
-
*
|
|
253
|
-
*
|
|
339
|
+
* Cap for the composed-config readback's LIST lines — Trigger codes, Root
|
|
340
|
+
* chain, Time slots, Roles, and Rules (qc2 Task-2 Minor): beyond this many
|
|
341
|
+
* items a line truncates with `…` while its leading count always stays the
|
|
342
|
+
* FULL count. Same sanity scale as {@link RECENT_SWITCHES_LIMIT}.
|
|
254
343
|
*/
|
|
255
344
|
export declare const FALLBACKS_CONFIG_LIST_CAP = 5;
|
|
256
345
|
/**
|
|
257
346
|
* Render the `/fallbacks config` surface (plan fallbacks-tui-client T2,
|
|
258
|
-
* AC-2): the composed `fallbacks`
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
347
|
+
* AC-2 + fallbacks-tui-settings Task 2 AC-4): the composed `fallbacks`
|
|
348
|
+
* namespace as the runtime reads it — enriched with the time-slot rows
|
|
349
|
+
* (preset rows resolve their frozen window from {@link PRESETS}), the
|
|
350
|
+
* config timezone, and the role rules — plus edit hints pointing at the
|
|
351
|
+
* `/settings` TUI edit surface while keeping the file-edit documentation.
|
|
352
|
+
* The FIRST LINE marks the composed-config readback — distinct from the
|
|
353
|
+
* diagnostic title and never merged into {@link fallbacksCommandText} (two
|
|
354
|
+
* operator surfaces, product lock). Locale defaults to `zh` (the command
|
|
355
|
+
* default); en dictionary tested.
|
|
263
356
|
*/
|
|
264
357
|
export declare function fallbacksConfigText(summary: FallbacksConfigSummary, locale?: FallbacksCommandLocale): string;
|
|
265
358
|
/**
|
package/dist/gateway.d.ts
CHANGED
|
@@ -214,6 +214,23 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
|
|
|
214
214
|
*/
|
|
215
215
|
private seedsIo;
|
|
216
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Reject a patch the `Config` schema cannot express: non-object input, unknown
|
|
219
|
+
* top-level keys (schemastery merges them silently — the settings service
|
|
220
|
+
* would accept them), and schema type violations — plus the Task 3 semantic
|
|
221
|
+
* guards the permissive schema deliberately does not carry: nested `roles`
|
|
222
|
+
* keys, `timeSlots` row shapes (unknown preset ids, duplicate presets, preset
|
|
223
|
+
* rows carrying windows, non-`HH:mm` custom bounds, out-of-range days, empty
|
|
224
|
+
* chains), and the all-day `rootChain` head conformance.
|
|
225
|
+
*
|
|
226
|
+
* Exported (plan fallbacks-tui-settings Task 1): the TUI settings section's
|
|
227
|
+
* JSON-field `parse` mirrors the gateway save rules through this single
|
|
228
|
+
* validator (it internally routes `timeSlots` → {@link validateTimeSlotsPatch}),
|
|
229
|
+
* so an invalid draft blocks the TUI save exactly like a rejected gateway
|
|
230
|
+
* patch. No shared-module extraction — the two-keyword diff is the minimal
|
|
231
|
+
* change.
|
|
232
|
+
*/
|
|
233
|
+
export declare function validateConfigPatch(patch: unknown): void;
|
|
217
234
|
/**
|
|
218
235
|
* The explicit typert contribution for the `fallbacks` gateway endpoints —
|
|
219
236
|
* registered via `ctx.typert.register(...)` (see `apply` in `src/index.ts`).
|