dsh-llm-fallbacks 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -9
- package/README.zh-CN.md +82 -9
- package/dist/automatch.d.ts +98 -0
- package/dist/client/FallbacksCard.d.ts +30 -15
- package/dist/client/fallbacks-store.d.ts +60 -10
- package/dist/client/index.d.ts +9 -7
- package/dist/client/index.js +2267 -985
- package/dist/client/locales.d.ts +140 -35
- package/dist/commands.d.ts +22 -7
- package/dist/config.d.ts +35 -1
- package/dist/events.d.ts +19 -5
- package/dist/index.d.ts +8 -5
- package/dist/index.js +620 -43
- package/dist/role-resolution.d.ts +81 -0
- package/dist/roles.d.ts +20 -5
- package/dist/time-slots.d.ts +104 -0
- package/dist/virtual-adapter.d.ts +90 -0
- package/package.json +20 -19
- package/scripts/repair-fallbacks-switch-logs.ts +374 -0
package/dist/client/locales.d.ts
CHANGED
|
@@ -37,15 +37,65 @@ export declare const zh: {
|
|
|
37
37
|
'advanced.label': string;
|
|
38
38
|
'advanced.expand': string;
|
|
39
39
|
'advanced.collapse': string;
|
|
40
|
+
'roleAutoMatch.label': string;
|
|
41
|
+
'roleAutoMatch.hint': string;
|
|
42
|
+
'roleAutoMatch.tooltip': string;
|
|
40
43
|
'rootChain.label': string;
|
|
41
|
-
'rootChain.hint': string;
|
|
42
44
|
'rootChain.tooltip': string;
|
|
43
|
-
'
|
|
45
|
+
'defaultModel.label': string;
|
|
44
46
|
'chains.selector.remove': string;
|
|
45
47
|
'chains.selector.providerPlaceholder': string;
|
|
46
48
|
'chains.selector.modelPlaceholder': string;
|
|
47
49
|
'chains.selector.wildcardLegacy': string;
|
|
48
50
|
'chains.selector.noModelsStrict': string;
|
|
51
|
+
'mainAgent.label': string;
|
|
52
|
+
'subagents.label': string;
|
|
53
|
+
'timeSlots.label': string;
|
|
54
|
+
'timeSlots.hint': string;
|
|
55
|
+
'timeSlots.tz.label': string;
|
|
56
|
+
'timeSlots.drag': string;
|
|
57
|
+
'timeSlots.name': string;
|
|
58
|
+
'timeSlots.expand': string;
|
|
59
|
+
'timeSlots.collapse': string;
|
|
60
|
+
'timeSlots.tooltip': string;
|
|
61
|
+
'timeSlots.addPreset': string;
|
|
62
|
+
'timeSlots.addCustom': string;
|
|
63
|
+
'timeSlots.presetPlaceholder': string;
|
|
64
|
+
'timeSlots.remove': string;
|
|
65
|
+
'timeSlots.moveUp': string;
|
|
66
|
+
'timeSlots.moveDown': string;
|
|
67
|
+
'timeSlots.start': string;
|
|
68
|
+
'timeSlots.end': string;
|
|
69
|
+
'timeSlots.days': string;
|
|
70
|
+
'timeSlots.days.hint': string;
|
|
71
|
+
'timeSlots.preset.name': string;
|
|
72
|
+
'timeSlots.preset.windowLabel': string;
|
|
73
|
+
'timeSlots.preset.chainsOnly': string;
|
|
74
|
+
'timeSlots.preset.liang-peak.label': string;
|
|
75
|
+
'timeSlots.preset.liang-peak.window': string;
|
|
76
|
+
'timeSlots.preset.liang-valley.label': string;
|
|
77
|
+
'timeSlots.preset.liang-valley.window': string;
|
|
78
|
+
'timeSlots.preset.glm-peak.label': string;
|
|
79
|
+
'timeSlots.preset.glm-peak.window': string;
|
|
80
|
+
'timeSlots.preset.glm-valley.label': string;
|
|
81
|
+
'timeSlots.preset.glm-valley.window': string;
|
|
82
|
+
'timeSlots.preset.glm.note': string;
|
|
83
|
+
'timeSlots.preset.highCost': string;
|
|
84
|
+
'timeSlots.preset.multiplier': string;
|
|
85
|
+
'timeSlots.active': string;
|
|
86
|
+
'timeSlots.preset.glm.unconfigured': string;
|
|
87
|
+
'timeSlots.day.sun': string;
|
|
88
|
+
'timeSlots.day.mon': string;
|
|
89
|
+
'timeSlots.day.tue': string;
|
|
90
|
+
'timeSlots.day.wed': string;
|
|
91
|
+
'timeSlots.day.thu': string;
|
|
92
|
+
'timeSlots.day.fri': string;
|
|
93
|
+
'timeSlots.day.sat': string;
|
|
94
|
+
'timeSlots.selector.add': string;
|
|
95
|
+
'allDay.hint': string;
|
|
96
|
+
'allDay.flash': string;
|
|
97
|
+
'allDay.pro': string;
|
|
98
|
+
'allDay.nonconforming': string;
|
|
49
99
|
'roles.list.label': string;
|
|
50
100
|
'roles.list.hint': string;
|
|
51
101
|
'roles.list.tooltip': string;
|
|
@@ -63,14 +113,12 @@ export declare const zh: {
|
|
|
63
113
|
'roles.fallback.none': string;
|
|
64
114
|
'roles.add': string;
|
|
65
115
|
'roles.remove': string;
|
|
116
|
+
'roles.expand': string;
|
|
117
|
+
'roles.collapse': string;
|
|
66
118
|
'roles.selector.add': string;
|
|
67
119
|
'roles.rules': string;
|
|
68
120
|
'roles.rules.hint': string;
|
|
69
121
|
'roles.rules.tooltip': string;
|
|
70
|
-
'roles.rule.origin': string;
|
|
71
|
-
'roles.rule.origin.any': string;
|
|
72
|
-
'roles.rule.origin.root': string;
|
|
73
|
-
'roles.rule.origin.subagent': string;
|
|
74
122
|
'roles.rule.provider': string;
|
|
75
123
|
'roles.rule.provider.any': string;
|
|
76
124
|
'roles.rule.model': string;
|
|
@@ -88,6 +136,14 @@ export declare const zh: {
|
|
|
88
136
|
'validation.ruleRoleUndeclared': string;
|
|
89
137
|
'validation.ruleRoleRequired': string;
|
|
90
138
|
'validation.roleChainRequired': string;
|
|
139
|
+
'validation.allDayRequired': string;
|
|
140
|
+
'validation.slotChainRequired': string;
|
|
141
|
+
'validation.slotWindow': string;
|
|
142
|
+
'validation.slotDays': string;
|
|
143
|
+
'validation.slotKind': string;
|
|
144
|
+
'validation.slotPresetUnknown': string;
|
|
145
|
+
'validation.slotPresetDuplicate': string;
|
|
146
|
+
'validation.slotPresetFrozen': string;
|
|
91
147
|
'validation.selector': string;
|
|
92
148
|
'legacy.banner': string;
|
|
93
149
|
'catalog.empty': string;
|
|
@@ -98,37 +154,32 @@ export declare const zh: {
|
|
|
98
154
|
'catalog.outside.short': string;
|
|
99
155
|
'catalog.unconfigured.short': string;
|
|
100
156
|
'status.title': string;
|
|
101
|
-
'status.effectiveModel.label': string;
|
|
102
|
-
'status.effectiveModel.unavailable': string;
|
|
103
|
-
'status.effectiveModel.note': string;
|
|
104
157
|
'status.switches.label': string;
|
|
105
158
|
'status.switches.empty': string;
|
|
106
159
|
'status.switches.error': string;
|
|
107
160
|
'status.switches.compact': string;
|
|
161
|
+
'status.switches.compact.roleInject': string;
|
|
108
162
|
'status.switches.reason.trigger-code': string;
|
|
109
163
|
'status.switches.reason.always-cap': string;
|
|
110
|
-
'status.
|
|
164
|
+
'status.switches.reason.role-inject': string;
|
|
111
165
|
'general.title': string;
|
|
112
166
|
'general.enabled': string;
|
|
113
167
|
'general.disabled': string;
|
|
114
168
|
'general.unknown': string;
|
|
115
169
|
'general.unavailable': string;
|
|
116
170
|
'general.switch': string;
|
|
171
|
+
'general.switch.roleInject': string;
|
|
117
172
|
'general.switch.empty': string;
|
|
118
173
|
'general.error': string;
|
|
119
174
|
'chat.switch.title': string;
|
|
120
175
|
'chat.switch.summary': string;
|
|
176
|
+
'chat.switch.summary.roleInject': string;
|
|
177
|
+
'chat.switch.roleMap': string;
|
|
121
178
|
'defaults.prefix': string;
|
|
122
179
|
save: string;
|
|
123
180
|
'save.saving': string;
|
|
124
181
|
'save.error': string;
|
|
125
182
|
close: string;
|
|
126
|
-
reset: string;
|
|
127
|
-
'reset.confirmTitle': string;
|
|
128
|
-
'reset.confirm': string;
|
|
129
|
-
'reset.confirm.cancel': string;
|
|
130
|
-
'reset.confirm.action': string;
|
|
131
|
-
'reset.saving': string;
|
|
132
183
|
loading: string;
|
|
133
184
|
unavailable: string;
|
|
134
185
|
'error.generic': string;
|
|
@@ -173,15 +224,65 @@ export declare const en: {
|
|
|
173
224
|
'advanced.label': string;
|
|
174
225
|
'advanced.expand': string;
|
|
175
226
|
'advanced.collapse': string;
|
|
227
|
+
'roleAutoMatch.label': string;
|
|
228
|
+
'roleAutoMatch.hint': string;
|
|
229
|
+
'roleAutoMatch.tooltip': string;
|
|
176
230
|
'rootChain.label': string;
|
|
177
|
-
'rootChain.hint': string;
|
|
178
231
|
'rootChain.tooltip': string;
|
|
179
|
-
'
|
|
232
|
+
'defaultModel.label': string;
|
|
180
233
|
'chains.selector.remove': string;
|
|
181
234
|
'chains.selector.providerPlaceholder': string;
|
|
182
235
|
'chains.selector.modelPlaceholder': string;
|
|
183
236
|
'chains.selector.wildcardLegacy': string;
|
|
184
237
|
'chains.selector.noModelsStrict': string;
|
|
238
|
+
'mainAgent.label': string;
|
|
239
|
+
'subagents.label': string;
|
|
240
|
+
'timeSlots.label': string;
|
|
241
|
+
'timeSlots.hint': string;
|
|
242
|
+
'timeSlots.tz.label': string;
|
|
243
|
+
'timeSlots.drag': string;
|
|
244
|
+
'timeSlots.name': string;
|
|
245
|
+
'timeSlots.expand': string;
|
|
246
|
+
'timeSlots.collapse': string;
|
|
247
|
+
'timeSlots.tooltip': string;
|
|
248
|
+
'timeSlots.addPreset': string;
|
|
249
|
+
'timeSlots.addCustom': string;
|
|
250
|
+
'timeSlots.presetPlaceholder': string;
|
|
251
|
+
'timeSlots.remove': string;
|
|
252
|
+
'timeSlots.moveUp': string;
|
|
253
|
+
'timeSlots.moveDown': string;
|
|
254
|
+
'timeSlots.start': string;
|
|
255
|
+
'timeSlots.end': string;
|
|
256
|
+
'timeSlots.days': string;
|
|
257
|
+
'timeSlots.days.hint': string;
|
|
258
|
+
'timeSlots.preset.name': string;
|
|
259
|
+
'timeSlots.preset.windowLabel': string;
|
|
260
|
+
'timeSlots.preset.chainsOnly': string;
|
|
261
|
+
'timeSlots.preset.liang-peak.label': string;
|
|
262
|
+
'timeSlots.preset.liang-peak.window': string;
|
|
263
|
+
'timeSlots.preset.liang-valley.label': string;
|
|
264
|
+
'timeSlots.preset.liang-valley.window': string;
|
|
265
|
+
'timeSlots.preset.glm-peak.label': string;
|
|
266
|
+
'timeSlots.preset.glm-peak.window': string;
|
|
267
|
+
'timeSlots.preset.glm-valley.label': string;
|
|
268
|
+
'timeSlots.preset.glm-valley.window': string;
|
|
269
|
+
'timeSlots.preset.glm.note': string;
|
|
270
|
+
'timeSlots.preset.highCost': string;
|
|
271
|
+
'timeSlots.preset.multiplier': string;
|
|
272
|
+
'timeSlots.active': string;
|
|
273
|
+
'timeSlots.preset.glm.unconfigured': string;
|
|
274
|
+
'timeSlots.day.sun': string;
|
|
275
|
+
'timeSlots.day.mon': string;
|
|
276
|
+
'timeSlots.day.tue': string;
|
|
277
|
+
'timeSlots.day.wed': string;
|
|
278
|
+
'timeSlots.day.thu': string;
|
|
279
|
+
'timeSlots.day.fri': string;
|
|
280
|
+
'timeSlots.day.sat': string;
|
|
281
|
+
'timeSlots.selector.add': string;
|
|
282
|
+
'allDay.hint': string;
|
|
283
|
+
'allDay.flash': string;
|
|
284
|
+
'allDay.pro': string;
|
|
285
|
+
'allDay.nonconforming': string;
|
|
185
286
|
'roles.list.label': string;
|
|
186
287
|
'roles.list.hint': string;
|
|
187
288
|
'roles.list.tooltip': string;
|
|
@@ -199,14 +300,12 @@ export declare const en: {
|
|
|
199
300
|
'roles.fallback.none': string;
|
|
200
301
|
'roles.add': string;
|
|
201
302
|
'roles.remove': string;
|
|
303
|
+
'roles.expand': string;
|
|
304
|
+
'roles.collapse': string;
|
|
202
305
|
'roles.selector.add': string;
|
|
203
306
|
'roles.rules': string;
|
|
204
307
|
'roles.rules.hint': string;
|
|
205
308
|
'roles.rules.tooltip': string;
|
|
206
|
-
'roles.rule.origin': string;
|
|
207
|
-
'roles.rule.origin.any': string;
|
|
208
|
-
'roles.rule.origin.root': string;
|
|
209
|
-
'roles.rule.origin.subagent': string;
|
|
210
309
|
'roles.rule.provider': string;
|
|
211
310
|
'roles.rule.provider.any': string;
|
|
212
311
|
'roles.rule.model': string;
|
|
@@ -224,6 +323,14 @@ export declare const en: {
|
|
|
224
323
|
'validation.ruleRoleUndeclared': string;
|
|
225
324
|
'validation.ruleRoleRequired': string;
|
|
226
325
|
'validation.roleChainRequired': string;
|
|
326
|
+
'validation.allDayRequired': string;
|
|
327
|
+
'validation.slotChainRequired': string;
|
|
328
|
+
'validation.slotWindow': string;
|
|
329
|
+
'validation.slotDays': string;
|
|
330
|
+
'validation.slotKind': string;
|
|
331
|
+
'validation.slotPresetUnknown': string;
|
|
332
|
+
'validation.slotPresetDuplicate': string;
|
|
333
|
+
'validation.slotPresetFrozen': string;
|
|
227
334
|
'validation.selector': string;
|
|
228
335
|
'legacy.banner': string;
|
|
229
336
|
'catalog.empty': string;
|
|
@@ -234,37 +341,32 @@ export declare const en: {
|
|
|
234
341
|
'catalog.outside.short': string;
|
|
235
342
|
'catalog.unconfigured.short': string;
|
|
236
343
|
'status.title': string;
|
|
237
|
-
'status.effectiveModel.label': string;
|
|
238
|
-
'status.effectiveModel.unavailable': string;
|
|
239
|
-
'status.effectiveModel.note': string;
|
|
240
344
|
'status.switches.label': string;
|
|
241
345
|
'status.switches.empty': string;
|
|
242
346
|
'status.switches.error': string;
|
|
243
347
|
'status.switches.compact': string;
|
|
348
|
+
'status.switches.compact.roleInject': string;
|
|
244
349
|
'status.switches.reason.trigger-code': string;
|
|
245
350
|
'status.switches.reason.always-cap': string;
|
|
246
|
-
'status.
|
|
351
|
+
'status.switches.reason.role-inject': string;
|
|
247
352
|
'general.title': string;
|
|
248
353
|
'general.enabled': string;
|
|
249
354
|
'general.disabled': string;
|
|
250
355
|
'general.unknown': string;
|
|
251
356
|
'general.unavailable': string;
|
|
252
357
|
'general.switch': string;
|
|
358
|
+
'general.switch.roleInject': string;
|
|
253
359
|
'general.switch.empty': string;
|
|
254
360
|
'general.error': string;
|
|
255
361
|
'chat.switch.title': string;
|
|
256
362
|
'chat.switch.summary': string;
|
|
363
|
+
'chat.switch.summary.roleInject': string;
|
|
364
|
+
'chat.switch.roleMap': string;
|
|
257
365
|
'defaults.prefix': string;
|
|
258
366
|
save: string;
|
|
259
367
|
'save.saving': string;
|
|
260
368
|
'save.error': string;
|
|
261
369
|
close: string;
|
|
262
|
-
reset: string;
|
|
263
|
-
'reset.confirmTitle': string;
|
|
264
|
-
'reset.confirm': string;
|
|
265
|
-
'reset.confirm.cancel': string;
|
|
266
|
-
'reset.confirm.action': string;
|
|
267
|
-
'reset.saving': string;
|
|
268
370
|
loading: string;
|
|
269
371
|
unavailable: string;
|
|
270
372
|
'error.generic': string;
|
|
@@ -279,9 +381,12 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
279
381
|
}
|
|
280
382
|
/**
|
|
281
383
|
* Reason → locale key map for switch summaries (S-c; shared by the card's
|
|
282
|
-
* status block
|
|
283
|
-
*
|
|
284
|
-
*
|
|
384
|
+
* status block, the General page status row, and the conversation node). All
|
|
385
|
+
* reasons resolve from ONE key family (`status.switches.reason.*`) — the
|
|
386
|
+
* shared reason vocabulary must not mix dictionary families (qc1 F-004). The
|
|
387
|
+
* session log is durable and forward-compatible: a reason value outside the
|
|
388
|
+
* current union (a newer plugin wrote it) renders raw instead of falling
|
|
389
|
+
* into a binary else branch.
|
|
285
390
|
*/
|
|
286
391
|
export declare const SWITCH_REASON_KEYS: Readonly<Partial<Record<FallbackSwitchReason, FallbacksKey>>>;
|
|
287
392
|
/** Human-readable trigger-code labels (spec §4 用户直观性). */
|
package/dist/commands.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ import type { CommandDefinition } from '@deepseek-ai/dsh-commands';
|
|
|
24
24
|
import { type FallbacksRole } from './config.ts';
|
|
25
25
|
import type { Origin } from './roles.ts';
|
|
26
26
|
import type { FallbacksSwitchEventData } from './events.ts';
|
|
27
|
+
import type { SlotRowConfig } from './time-slots.ts';
|
|
27
28
|
/** How many recent `fallbacks/switch` events `/fallbacks` shows (newest first). */
|
|
28
29
|
export declare const RECENT_SWITCHES_LIMIT = 5;
|
|
29
30
|
/** Minimal command registry surface (satisfied by the dsh `CommandService`). */
|
|
@@ -68,7 +69,15 @@ export interface FallbacksCommandSnapshot {
|
|
|
68
69
|
* `fallback` is `'inherit-root'` — or the role is unknown — and rootChain
|
|
69
70
|
* is non-empty; the diagnostic annotation source, spec §7.4). */
|
|
70
71
|
readonly inherit: boolean;
|
|
71
|
-
/**
|
|
72
|
+
/** Current time-slot winner + display label (P5/P7): the 分时切换 side of
|
|
73
|
+
* the status strip. The switches section below is the 降级切换 side —
|
|
74
|
+
* the copy never mixes. */
|
|
75
|
+
readonly slot: {
|
|
76
|
+
readonly winner: SlotRowConfig | 'all-day';
|
|
77
|
+
readonly label: string;
|
|
78
|
+
};
|
|
79
|
+
/** Recent `fallbacks/switch` events (failure walks — 降级切换), newest
|
|
80
|
+
* first, capped at {@link RECENT_SWITCHES_LIMIT}. */
|
|
72
81
|
readonly switches: readonly FallbacksSwitchEventData[];
|
|
73
82
|
/** Active cooldown entries for the agent. */
|
|
74
83
|
readonly cooldown: readonly FallbacksCooldownEntry[];
|
|
@@ -95,6 +104,8 @@ export interface FallbacksConfigSummary {
|
|
|
95
104
|
readonly maxSwitchesPerStep: number;
|
|
96
105
|
readonly alwaysModeRetryCap: number;
|
|
97
106
|
readonly presets: 'bundled' | 'none';
|
|
107
|
+
/** Dispatch-time LLM role auto-match switch (default true). */
|
|
108
|
+
readonly roleAutoMatch: boolean;
|
|
98
109
|
}
|
|
99
110
|
/**
|
|
100
111
|
* The session-scoped read-only operations the `/fallbacks` handler drives.
|
|
@@ -116,7 +127,7 @@ export interface FallbacksCommandController {
|
|
|
116
127
|
export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
117
128
|
readonly zh: {
|
|
118
129
|
readonly title: "当前会话 fallback 诊断(只读)";
|
|
119
|
-
readonly description: "
|
|
130
|
+
readonly description: "查看当前会话的降级链、最近降级切换与冷却状态(只读)";
|
|
120
131
|
readonly usageConfig: "查看组合后的 fallbacks 配置(设置回读)";
|
|
121
132
|
readonly usage: " /fallbacks config 查看组合后的 fallbacks 配置(设置回读)";
|
|
122
133
|
readonly origin: "会话来源";
|
|
@@ -124,7 +135,8 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
124
135
|
readonly chain: "链";
|
|
125
136
|
readonly inheritRoot: "(inherit-root)";
|
|
126
137
|
readonly chainNone: "未配置";
|
|
127
|
-
readonly
|
|
138
|
+
readonly slot: "分时";
|
|
139
|
+
readonly switches: "最近降级切换";
|
|
128
140
|
readonly switchesNone: "本会话暂无 fallback 切换";
|
|
129
141
|
readonly switchLine: "{from} → {to}(role={role},reason={reason})";
|
|
130
142
|
readonly cooldown: "冷却";
|
|
@@ -148,12 +160,13 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
148
160
|
readonly configMaxSwitches: "单步最大切换";
|
|
149
161
|
readonly configAlwaysCap: "always 上限";
|
|
150
162
|
readonly configPresets: "预置";
|
|
163
|
+
readonly configRoleAutoMatch: "角色自动匹配";
|
|
151
164
|
readonly configEdit: "编辑:~/.dsh/profiles/<profile>/cordis.patch.yml(插件行)或 $DSH_HOME/settings.yaml(fallbacks: 分节)";
|
|
152
165
|
readonly configEditHint: "TUI 无法修改配置——只能编辑文件";
|
|
153
166
|
};
|
|
154
167
|
readonly en: {
|
|
155
168
|
readonly title: "Session fallback diagnostics (read-only)";
|
|
156
|
-
readonly description: "Inspect fallback chain, recent switches, and cooldown for this session (read-only)";
|
|
169
|
+
readonly description: "Inspect fallback chain, recent fallback switches, and cooldown for this session (read-only)";
|
|
157
170
|
readonly usageConfig: "show the composed fallbacks config (settings readback)";
|
|
158
171
|
readonly usage: " /fallbacks config show the composed fallbacks config (settings readback)";
|
|
159
172
|
readonly origin: "Session origin";
|
|
@@ -161,7 +174,8 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
161
174
|
readonly chain: "Chain";
|
|
162
175
|
readonly inheritRoot: " (inherit-root)";
|
|
163
176
|
readonly chainNone: "not configured";
|
|
164
|
-
readonly
|
|
177
|
+
readonly slot: "Time slot";
|
|
178
|
+
readonly switches: "Recent fallback switches";
|
|
165
179
|
readonly switchesNone: "No fallback switches in this session";
|
|
166
180
|
readonly switchLine: "{from} → {to} (role={role}, reason={reason})";
|
|
167
181
|
readonly cooldown: "Cooldown";
|
|
@@ -185,6 +199,7 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
185
199
|
readonly configMaxSwitches: "Max switches/step";
|
|
186
200
|
readonly configAlwaysCap: "Always-mode cap";
|
|
187
201
|
readonly configPresets: "Presets";
|
|
202
|
+
readonly configRoleAutoMatch: "Auto-match";
|
|
188
203
|
readonly configEdit: "Edit: ~/.dsh/profiles/<profile>/cordis.patch.yml (plugin row) or $DSH_HOME/settings.yaml (fallbacks: section)";
|
|
189
204
|
readonly configEditHint: "TUI cannot change config — edit files only";
|
|
190
205
|
};
|
|
@@ -249,8 +264,8 @@ export declare const FALLBACKS_CONFIG_LIST_CAP = 5;
|
|
|
249
264
|
export declare function fallbacksConfigText(summary: FallbacksConfigSummary, locale?: FallbacksCommandLocale): string;
|
|
250
265
|
/**
|
|
251
266
|
* Render the `/fallbacks` status surface for one snapshot. Kept minimal and
|
|
252
|
-
* truthful: origin → role → chain (+ inherit tail) →
|
|
253
|
-
* cooldown.
|
|
267
|
+
* truthful: origin → role → chain (+ inherit tail) → current slot (分时) →
|
|
268
|
+
* recent switches (降级切换) → cooldown.
|
|
254
269
|
*/
|
|
255
270
|
export declare function fallbacksCommandText(snapshot: FallbacksCommandSnapshot, locale?: FallbacksCommandLocale): string;
|
|
256
271
|
/**
|
package/dist/config.d.ts
CHANGED
|
@@ -27,10 +27,17 @@
|
|
|
27
27
|
*
|
|
28
28
|
* @module dsh-llm-fallbacks/config
|
|
29
29
|
*/
|
|
30
|
+
import type { SlotRowConfig } from './time-slots.ts';
|
|
30
31
|
/** How a cooled-down model comes back (spec §4). */
|
|
31
32
|
export type RevertPolicy = 'cooldown-expiry' | 'never';
|
|
32
|
-
/** A single role rule: match on
|
|
33
|
+
/** A single role rule: match on provider/model patterns (spec §3). */
|
|
33
34
|
export interface FallbacksRoleRule {
|
|
35
|
+
/**
|
|
36
|
+
* Legacy persisted wire field (PR #62 feedback): rules are subagent-only,
|
|
37
|
+
* so this constraint is IGNORED at match time — root requests never
|
|
38
|
+
* match rules. Kept in the type/schema so pre-feedback `settings.yaml`
|
|
39
|
+
* files that carry `origin` still parse, validate, and save unchanged.
|
|
40
|
+
*/
|
|
34
41
|
origin?: 'root' | 'subagent';
|
|
35
42
|
provider?: string;
|
|
36
43
|
model?: string;
|
|
@@ -91,6 +98,33 @@ export interface FallbacksConfig {
|
|
|
91
98
|
* every resolved config carries a value via the schema default.
|
|
92
99
|
*/
|
|
93
100
|
presets?: 'bundled' | 'none';
|
|
101
|
+
/**
|
|
102
|
+
* Dispatch-time LLM role auto-match switch (plan fallbacks-role-automatch
|
|
103
|
+
* Task 1): when `true` (default), a subagent-origin request with no
|
|
104
|
+
* explicit/rules-resolved role may have the best-fit declared role picked
|
|
105
|
+
* by the LLM; `false` reproduces today's behavior exactly. Optional on
|
|
106
|
+
* purpose, mirroring `presets` — a required field would break library
|
|
107
|
+
* consumers that construct `FallbacksConfig` literals with the existing
|
|
108
|
+
* keys (additive, non-breaking). The value domain is guarded by the
|
|
109
|
+
* schema (`z.boolean().default(true)` in `src/schema.ts`), and the
|
|
110
|
+
* runtime reads it defensively as `config.roleAutoMatch ?? true` (safe
|
|
111
|
+
* for direct constructors that omit it).
|
|
112
|
+
*/
|
|
113
|
+
roleAutoMatch?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Extra time-slot rows (plan fallbacks-timeslots Task 1, P5): the FIRST
|
|
116
|
+
* matching row's chain becomes the effective root chain at request time;
|
|
117
|
+
* `rootChain` (the all-day chain) is always the last row.
|
|
118
|
+
* Optional on purpose, mirroring `presets` — additive, non-breaking for
|
|
119
|
+
* library consumers. Malformed rows warn once and are skipped by the
|
|
120
|
+
* resolver; the gateway rejects them on save (Task 3).
|
|
121
|
+
*/
|
|
122
|
+
timeSlots?: SlotRowConfig[];
|
|
123
|
+
/**
|
|
124
|
+
* Config-level timezone for slot matching (default `Asia/Shanghai`,
|
|
125
|
+
* UTC+8). Not per-slot.
|
|
126
|
+
*/
|
|
127
|
+
tz?: string;
|
|
94
128
|
}
|
|
95
129
|
/**
|
|
96
130
|
* Spec §4 defaults — `Config({})` must equal this (no-op install).
|
package/dist/events.d.ts
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `fallbacks/switch` session event vocabulary (spec §5 table; plan Task 3).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Writing is stopped (issue #52): the plugin no longer appends this event —
|
|
5
|
+
* the apply()-time event-type registration was proven ineffective (module
|
|
6
|
+
* instance mismatch), and a session containing the event refused to load
|
|
7
|
+
* after a dsh restart. The event now exists only in history: old logs are
|
|
8
|
+
* repaired by `scripts/repair-fallbacks-switch-logs.ts`, which marks legacy
|
|
9
|
+
* events ignorable so affected sessions load again.
|
|
6
10
|
* The module is type-only — the augmentation is erased at runtime; the
|
|
7
11
|
* plugin's runtime behavior lives in `src/index.ts`.
|
|
8
12
|
*
|
|
9
13
|
* @module dsh-llm-fallbacks/events
|
|
10
14
|
*/
|
|
11
|
-
/**
|
|
12
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Why a switch was decided (spec §5.1 `PendingSwitch.reason`).
|
|
17
|
+
*
|
|
18
|
+
* `role-inject` is the dispatch-time reason (plan fallbacks-role-automatch
|
|
19
|
+
* Task 4): a subagent-origin agent's first request was re-routed to its
|
|
20
|
+
* resolved role's chain head. It is ADDITIVE to the failure-time reasons —
|
|
21
|
+
* the event shape stays a superset of the pre-feature payload, and existing
|
|
22
|
+
* renderers show unknown reasons raw (AC-5). Unlike `trigger-code` /
|
|
23
|
+
* `always-cap`, a `role-inject` event is NOT a failure decision: it carries
|
|
24
|
+
* no pending switch / cooldown / failure bookkeeping (no `commit()`).
|
|
25
|
+
*/
|
|
26
|
+
export type FallbackSwitchReason = 'trigger-code' | 'always-cap' | 'role-inject';
|
|
13
27
|
/** Durable payload of one provider/model switch (spec §5 table). */
|
|
14
28
|
export interface FallbacksSwitchEventData {
|
|
15
29
|
turn: number;
|
|
@@ -30,7 +44,7 @@ export interface FallbacksSwitchEventData {
|
|
|
30
44
|
}
|
|
31
45
|
declare module '@deepseek-ai/dsh-session/types' {
|
|
32
46
|
interface SessionEventMap {
|
|
33
|
-
/**
|
|
47
|
+
/** Historical, append-only record of one provider/model switch decided by dsh-llm-fallbacks (no longer written — issue #52 stop-write). */
|
|
34
48
|
'fallbacks/switch': FallbacksSwitchEventData;
|
|
35
49
|
}
|
|
36
50
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,14 +13,17 @@
|
|
|
13
13
|
* (**always mode included**) → `next()`; otherwise resolve role + chain,
|
|
14
14
|
* and when a candidate survives the filter (current / cooldown /
|
|
15
15
|
* step-failed / `provider/*`-missing-id) write the pending switch +
|
|
16
|
-
* cooldown + failure bookkeeping
|
|
16
|
+
* cooldown + failure bookkeeping, then return
|
|
17
17
|
* `{ kind: 'retry' }` (own recovery, no `next()`).
|
|
18
18
|
* - `agent/request` waterfall: apply a pending switch after `await next()`
|
|
19
19
|
* (provider/model override, inherited `reasoningEffort` dropped — the
|
|
20
|
-
* `installModelSelection` `withoutInheritedEffort` pattern)
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* `installModelSelection` `withoutInheritedEffort` pattern); a
|
|
21
|
+
* root-origin `FallbacksChain/Auto` seed then overrides to the
|
|
22
|
+
* effective chain's first exact head (select-is-primary, plan
|
|
23
|
+
* fallbacks-virtual-chain Task 2); then the always-mode cap check (count
|
|
24
|
+
* `llm/retry` events for the current turn/step/provider; ≥
|
|
25
|
+
* `alwaysModeRetryCap` → same decision path, reason `always-cap` —
|
|
26
|
+
* ADR-2).
|
|
24
27
|
* - Per-agent state (`FallbackStateStore`): `agent/disposed` removes it,
|
|
25
28
|
* `agent/status` idle prunes per-step state defensively, plugin dispose
|
|
26
29
|
* clears everything (spec §6 — no residual state).
|