dsh-llm-fallbacks 0.2.2 → 0.3.1
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 +67 -9
- package/README.zh-CN.md +66 -8
- package/dist/client/FallbacksCard.d.ts +27 -13
- package/dist/client/GeneralFallbacksRow.d.ts +1 -1
- package/dist/client/fallbacks-store.d.ts +48 -4
- package/dist/client/index.js +2349 -938
- package/dist/client/locales.d.ts +118 -26
- package/dist/client/use-snapshot.d.ts +11 -0
- package/dist/commands.d.ts +18 -7
- package/dist/config.d.ts +22 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.js +467 -15
- package/dist/roles.d.ts +12 -5
- package/dist/time-slots.d.ts +104 -0
- package/dist/virtual-adapter.d.ts +90 -0
- package/package.json +26 -23
- package/scripts/build-client.ts +9 -9
package/dist/client/index.js
CHANGED
|
@@ -4,11 +4,170 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
|
|
7
|
+
//#region \0rolldown/runtime.js
|
|
8
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
9
|
+
//#endregion
|
|
8
10
|
let react = require("react");
|
|
9
11
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
12
|
let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
11
13
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
14
|
+
//#region node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js
|
|
15
|
+
/**
|
|
16
|
+
* @license React
|
|
17
|
+
* use-sync-external-store-shim.production.js
|
|
18
|
+
*
|
|
19
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
20
|
+
*
|
|
21
|
+
* This source code is licensed under the MIT license found in the
|
|
22
|
+
* LICENSE file in the root directory of this source tree.
|
|
23
|
+
*/
|
|
24
|
+
var require_use_sync_external_store_shim_production = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
25
|
+
var React$1 = require("react");
|
|
26
|
+
function is(x, y) {
|
|
27
|
+
return x === y && (0 !== x || 1 / x === 1 / y) || x !== x && y !== y;
|
|
28
|
+
}
|
|
29
|
+
var objectIs = "function" === typeof Object.is ? Object.is : is;
|
|
30
|
+
var useState = React$1.useState;
|
|
31
|
+
var useEffect = React$1.useEffect;
|
|
32
|
+
var useLayoutEffect = React$1.useLayoutEffect;
|
|
33
|
+
var useDebugValue = React$1.useDebugValue;
|
|
34
|
+
function useSyncExternalStore$2(subscribe, getSnapshot) {
|
|
35
|
+
var value = getSnapshot(), _useState = useState({ inst: {
|
|
36
|
+
value,
|
|
37
|
+
getSnapshot
|
|
38
|
+
} }), inst = _useState[0].inst, forceUpdate = _useState[1];
|
|
39
|
+
useLayoutEffect(function() {
|
|
40
|
+
inst.value = value;
|
|
41
|
+
inst.getSnapshot = getSnapshot;
|
|
42
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
43
|
+
}, [
|
|
44
|
+
subscribe,
|
|
45
|
+
value,
|
|
46
|
+
getSnapshot
|
|
47
|
+
]);
|
|
48
|
+
useEffect(function() {
|
|
49
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
50
|
+
return subscribe(function() {
|
|
51
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst });
|
|
52
|
+
});
|
|
53
|
+
}, [subscribe]);
|
|
54
|
+
useDebugValue(value);
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
function checkIfSnapshotChanged(inst) {
|
|
58
|
+
var latestGetSnapshot = inst.getSnapshot;
|
|
59
|
+
inst = inst.value;
|
|
60
|
+
try {
|
|
61
|
+
var nextValue = latestGetSnapshot();
|
|
62
|
+
return !objectIs(inst, nextValue);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
return !0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function useSyncExternalStore$1(subscribe, getSnapshot) {
|
|
68
|
+
return getSnapshot();
|
|
69
|
+
}
|
|
70
|
+
var shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
|
|
71
|
+
exports.useSyncExternalStore = void 0 !== React$1.useSyncExternalStore ? React$1.useSyncExternalStore : shim;
|
|
72
|
+
}));
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region node_modules/use-sync-external-store/shim/index.js
|
|
75
|
+
var require_shim = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
76
|
+
module.exports = require_use_sync_external_store_shim_production();
|
|
77
|
+
}));
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js
|
|
80
|
+
/**
|
|
81
|
+
* @license React
|
|
82
|
+
* use-sync-external-store-shim/with-selector.production.js
|
|
83
|
+
*
|
|
84
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
85
|
+
*
|
|
86
|
+
* This source code is licensed under the MIT license found in the
|
|
87
|
+
* LICENSE file in the root directory of this source tree.
|
|
88
|
+
*/
|
|
89
|
+
var require_with_selector_production = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
90
|
+
var React = require("react");
|
|
91
|
+
var shim = require_shim();
|
|
92
|
+
function is(x, y) {
|
|
93
|
+
return x === y && (0 !== x || 1 / x === 1 / y) || x !== x && y !== y;
|
|
94
|
+
}
|
|
95
|
+
var objectIs = "function" === typeof Object.is ? Object.is : is;
|
|
96
|
+
var useSyncExternalStore = shim.useSyncExternalStore;
|
|
97
|
+
var useRef = React.useRef;
|
|
98
|
+
var useEffect = React.useEffect;
|
|
99
|
+
var useMemo = React.useMemo;
|
|
100
|
+
var useDebugValue = React.useDebugValue;
|
|
101
|
+
exports.useSyncExternalStoreWithSelector = function(subscribe, getSnapshot, getServerSnapshot, selector, isEqual) {
|
|
102
|
+
var instRef = useRef(null);
|
|
103
|
+
if (null === instRef.current) {
|
|
104
|
+
var inst = {
|
|
105
|
+
hasValue: !1,
|
|
106
|
+
value: null
|
|
107
|
+
};
|
|
108
|
+
instRef.current = inst;
|
|
109
|
+
} else inst = instRef.current;
|
|
110
|
+
instRef = useMemo(function() {
|
|
111
|
+
function memoizedSelector(nextSnapshot) {
|
|
112
|
+
if (!hasMemo) {
|
|
113
|
+
hasMemo = !0;
|
|
114
|
+
memoizedSnapshot = nextSnapshot;
|
|
115
|
+
nextSnapshot = selector(nextSnapshot);
|
|
116
|
+
if (void 0 !== isEqual && inst.hasValue) {
|
|
117
|
+
var currentSelection = inst.value;
|
|
118
|
+
if (isEqual(currentSelection, nextSnapshot)) return memoizedSelection = currentSelection;
|
|
119
|
+
}
|
|
120
|
+
return memoizedSelection = nextSnapshot;
|
|
121
|
+
}
|
|
122
|
+
currentSelection = memoizedSelection;
|
|
123
|
+
if (objectIs(memoizedSnapshot, nextSnapshot)) return currentSelection;
|
|
124
|
+
var nextSelection = selector(nextSnapshot);
|
|
125
|
+
if (void 0 !== isEqual && isEqual(currentSelection, nextSelection)) return memoizedSnapshot = nextSnapshot, currentSelection;
|
|
126
|
+
memoizedSnapshot = nextSnapshot;
|
|
127
|
+
return memoizedSelection = nextSelection;
|
|
128
|
+
}
|
|
129
|
+
var hasMemo = !1, memoizedSnapshot, memoizedSelection, maybeGetServerSnapshot = void 0 === getServerSnapshot ? null : getServerSnapshot;
|
|
130
|
+
return [function() {
|
|
131
|
+
return memoizedSelector(getSnapshot());
|
|
132
|
+
}, null === maybeGetServerSnapshot ? void 0 : function() {
|
|
133
|
+
return memoizedSelector(maybeGetServerSnapshot());
|
|
134
|
+
}];
|
|
135
|
+
}, [
|
|
136
|
+
getSnapshot,
|
|
137
|
+
getServerSnapshot,
|
|
138
|
+
selector,
|
|
139
|
+
isEqual
|
|
140
|
+
]);
|
|
141
|
+
var value = useSyncExternalStore(subscribe, instRef[0], instRef[1]);
|
|
142
|
+
useEffect(function() {
|
|
143
|
+
inst.hasValue = !0;
|
|
144
|
+
inst.value = value;
|
|
145
|
+
}, [value]);
|
|
146
|
+
useDebugValue(value);
|
|
147
|
+
return value;
|
|
148
|
+
};
|
|
149
|
+
}));
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/client/use-snapshot.ts
|
|
152
|
+
var import_with_selector = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
153
|
+
module.exports = require_with_selector_production();
|
|
154
|
+
})))();
|
|
155
|
+
/**
|
|
156
|
+
* Bind a bare observable source to a typed uSES selector hook.
|
|
157
|
+
* subscribe/getSnapshot are captured once per source into stable closures
|
|
158
|
+
* (also re-binds `this` for method-based sources), so components never
|
|
159
|
+
* resubscribe across renders. Equality defaults to Object.is.
|
|
160
|
+
* @param w - snapshot source (engine store, Session object, store instance).
|
|
161
|
+
* @returns the selector hook.
|
|
162
|
+
*/
|
|
163
|
+
function bindSnapshotSelector(w) {
|
|
164
|
+
const subscribe = (fn) => w.subscribe(fn);
|
|
165
|
+
const getSnapshot = () => w.getSnapshot();
|
|
166
|
+
return function useSelector(sel, eq) {
|
|
167
|
+
return (0, import_with_selector.useSyncExternalStoreWithSelector)(subscribe, getSnapshot, void 0, sel, eq);
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//#endregion
|
|
12
171
|
//#region src/selectors.ts
|
|
13
172
|
/** Catchable error for illegal/unknown selectors (config-warning path). */
|
|
14
173
|
var SelectorError = class extends Error {
|
|
@@ -38,6 +197,238 @@ window.__ModuleLoader__.load({
|
|
|
38
197
|
raw: trimmed
|
|
39
198
|
};
|
|
40
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Frozen preset windows (UTC+8). `liang-*` presets have NO day mask (they
|
|
202
|
+
* apply every day, weekends included); `glm-peak` is Monday–Friday only.
|
|
203
|
+
* The two valleys are `complement: true` of their peak.
|
|
204
|
+
*/
|
|
205
|
+
const PRESETS = {
|
|
206
|
+
"liang-peak": {
|
|
207
|
+
windows: [{
|
|
208
|
+
start: "09:00",
|
|
209
|
+
end: "12:00"
|
|
210
|
+
}, {
|
|
211
|
+
start: "14:00",
|
|
212
|
+
end: "18:00"
|
|
213
|
+
}],
|
|
214
|
+
complement: false,
|
|
215
|
+
label: "Liang Peak"
|
|
216
|
+
},
|
|
217
|
+
"liang-valley": {
|
|
218
|
+
windows: [{
|
|
219
|
+
start: "09:00",
|
|
220
|
+
end: "12:00"
|
|
221
|
+
}, {
|
|
222
|
+
start: "14:00",
|
|
223
|
+
end: "18:00"
|
|
224
|
+
}],
|
|
225
|
+
complement: true,
|
|
226
|
+
label: "Liang Valley"
|
|
227
|
+
},
|
|
228
|
+
"glm-peak": {
|
|
229
|
+
windows: [{
|
|
230
|
+
start: "14:00",
|
|
231
|
+
end: "18:00",
|
|
232
|
+
days: [
|
|
233
|
+
1,
|
|
234
|
+
2,
|
|
235
|
+
3,
|
|
236
|
+
4,
|
|
237
|
+
5
|
|
238
|
+
]
|
|
239
|
+
}],
|
|
240
|
+
complement: false,
|
|
241
|
+
label: "GLM Peak"
|
|
242
|
+
},
|
|
243
|
+
"glm-valley": {
|
|
244
|
+
windows: [{
|
|
245
|
+
start: "14:00",
|
|
246
|
+
end: "18:00",
|
|
247
|
+
days: [
|
|
248
|
+
1,
|
|
249
|
+
2,
|
|
250
|
+
3,
|
|
251
|
+
4,
|
|
252
|
+
5
|
|
253
|
+
]
|
|
254
|
+
}],
|
|
255
|
+
complement: true,
|
|
256
|
+
label: "GLM Valley"
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
const HHMM_RE$1 = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
260
|
+
const WEEKDAY_INDEX = {
|
|
261
|
+
Sun: 0,
|
|
262
|
+
Mon: 1,
|
|
263
|
+
Tue: 2,
|
|
264
|
+
Wed: 3,
|
|
265
|
+
Thu: 4,
|
|
266
|
+
Fri: 5,
|
|
267
|
+
Sat: 6
|
|
268
|
+
};
|
|
269
|
+
/** Malformed rows warn once per row INSTANCE (config snapshots are stable
|
|
270
|
+
* across requests — this is what keeps "warn once" from becoming spam). */
|
|
271
|
+
const warnedMalformedRows = /* @__PURE__ */ new WeakSet();
|
|
272
|
+
/** Invalid `tz` values warn once per distinct value. */
|
|
273
|
+
const warnedTimeZones = /* @__PURE__ */ new Set();
|
|
274
|
+
function warnMalformed(row, reason) {
|
|
275
|
+
if (typeof row !== "object" || row === null) {
|
|
276
|
+
console.warn(`llm-fallbacks: skipping malformed time-slot row (${reason})`);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (warnedMalformedRows.has(row)) return;
|
|
280
|
+
warnedMalformedRows.add(row);
|
|
281
|
+
console.warn(`llm-fallbacks: skipping malformed time-slot row (${reason}): ${JSON.stringify(row)}`);
|
|
282
|
+
}
|
|
283
|
+
/** Wall-clock weekday (0=Sunday) + minutes-since-midnight of `now` in `tz`
|
|
284
|
+
* (standard `Intl` timezone rules, DST-safe). */
|
|
285
|
+
function wallClock(now, tz) {
|
|
286
|
+
try {
|
|
287
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
288
|
+
timeZone: tz,
|
|
289
|
+
weekday: "short",
|
|
290
|
+
hour: "2-digit",
|
|
291
|
+
minute: "2-digit",
|
|
292
|
+
hourCycle: "h23"
|
|
293
|
+
}).formatToParts(now);
|
|
294
|
+
let weekday = 0;
|
|
295
|
+
let minutes = 0;
|
|
296
|
+
for (const part of parts) if (part.type === "weekday") weekday = WEEKDAY_INDEX[part.value] ?? 0;
|
|
297
|
+
else if (part.type === "hour") minutes += Number(part.value) * 60;
|
|
298
|
+
else if (part.type === "minute") minutes += Number(part.value);
|
|
299
|
+
return {
|
|
300
|
+
weekday,
|
|
301
|
+
minutes
|
|
302
|
+
};
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (!warnedTimeZones.has(tz)) {
|
|
305
|
+
warnedTimeZones.add(tz);
|
|
306
|
+
console.warn(`llm-fallbacks: invalid timezone "${tz}" (${error.message}) — slot matching falls back to UTC`);
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
weekday: now.getUTCDay(),
|
|
310
|
+
minutes: now.getUTCHours() * 60 + now.getUTCMinutes()
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/** `HH:mm` → minutes-since-midnight (inputs are regex-validated or frozen
|
|
315
|
+
* constants — this never sees garbage). */
|
|
316
|
+
function minutesOf(hhmm) {
|
|
317
|
+
const [hour, minute] = hhmm.split(":").map(Number);
|
|
318
|
+
return hour * 60 + minute;
|
|
319
|
+
}
|
|
320
|
+
/** P4 containment rule: day mask matches AND the window contains `t`
|
|
321
|
+
* (`end` exclusive; `start > end` wraps midnight — custom rows only). */
|
|
322
|
+
function containsWindow(window, clock) {
|
|
323
|
+
if (!(window.days === void 0 || window.days.length === 0 || window.days.includes(clock.weekday))) return false;
|
|
324
|
+
const start = minutesOf(window.start);
|
|
325
|
+
const end = minutesOf(window.end);
|
|
326
|
+
return start <= end ? start <= clock.minutes && clock.minutes < end : start <= clock.minutes || clock.minutes < end;
|
|
327
|
+
}
|
|
328
|
+
function matchesAnyWindow(windows, clock) {
|
|
329
|
+
return windows.some((window) => containsWindow(window, clock));
|
|
330
|
+
}
|
|
331
|
+
/** Validate one stored row → frozen windows, or `undefined` (warn once +
|
|
332
|
+
* skip). Preset rows reject stored windows/day masks (P4); custom rows
|
|
333
|
+
* require strict `HH:mm` bounds; chains must be non-empty. */
|
|
334
|
+
function describeRow(row) {
|
|
335
|
+
if (!Array.isArray(row.chain) || row.chain.length === 0) {
|
|
336
|
+
warnMalformed(row, "empty chain");
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (row.kind === "preset") {
|
|
340
|
+
const preset = row.preset;
|
|
341
|
+
if (typeof preset !== "string" || !Object.hasOwn(PRESETS, preset)) {
|
|
342
|
+
warnMalformed(row, `unknown preset ${JSON.stringify(preset)}`);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (row.start !== void 0 || row.end !== void 0 || row.days !== void 0 && row.days.length > 0) {
|
|
346
|
+
warnMalformed(row, `preset windows are fixed — row "${preset}" cannot carry start/end/days`);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
return PRESETS[preset];
|
|
350
|
+
}
|
|
351
|
+
if (row.kind === "custom") {
|
|
352
|
+
const { start, end } = row;
|
|
353
|
+
if (typeof start !== "string" || typeof end !== "string" || !HHMM_RE$1.test(start) || !HHMM_RE$1.test(end)) {
|
|
354
|
+
warnMalformed(row, `invalid custom window ${JSON.stringify(start)}-${JSON.stringify(end)} (expected HH:mm)`);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
windows: [{
|
|
359
|
+
start,
|
|
360
|
+
end,
|
|
361
|
+
days: row.days
|
|
362
|
+
}],
|
|
363
|
+
complement: false
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
warnMalformed(row, `unknown kind ${JSON.stringify(row.kind)}`);
|
|
367
|
+
}
|
|
368
|
+
/** Display label for a winning row (preset rows use the frozen label;
|
|
369
|
+
* custom rows prefer their display name, falling back to the window). */
|
|
370
|
+
function labelOf(row) {
|
|
371
|
+
if (row.kind === "preset" && typeof row.preset === "string" && Object.hasOwn(PRESETS, row.preset)) return PRESETS[row.preset].label;
|
|
372
|
+
return row.name !== void 0 && row.name.trim() !== "" ? row.name : `custom ${row.start}-${row.end}`;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* All-day conformance (P6): the all-day chain is conforming when its LAST
|
|
376
|
+
* entry (the tail — the card's 默认模型 panel) is exactly one official V4
|
|
377
|
+
* model — Flash XOR Pro. Leading entries (the card's 默认降级链 block) are
|
|
378
|
+
* the ordered walk before that last-resort fallback. An empty chain or a
|
|
379
|
+
* chain whose tail is not an official V4 model keeps slot rows inert and
|
|
380
|
+
* refuses the virtual-row override/delegate; the v0.2.2 failure walk over
|
|
381
|
+
* the raw chain stays verbatim.
|
|
382
|
+
*/
|
|
383
|
+
function isAllDayConforming(chain) {
|
|
384
|
+
if (chain.length < 1) return false;
|
|
385
|
+
const tail = chain[chain.length - 1];
|
|
386
|
+
return tail === "deepseek-official/deepseek-v4-flash" || tail === "deepseek-official/deepseek-v4-pro";
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Slot winner + display label (P5): drives 分时切换 detection (per-root-agent
|
|
390
|
+
* last-winner marker, in-process only) and the card / `/fallbacks` status
|
|
391
|
+
* strip. `winner` is the matching row or `'all-day'`; `label` names the
|
|
392
|
+
* slot (frozen preset label or `custom HH:mm-HH:mm`).
|
|
393
|
+
*
|
|
394
|
+
* P6 gate (qc1 F-001): without a conforming all-day
|
|
395
|
+
* (`isAllDayConforming(config.rootChain)`) the winner is ALWAYS `'all-day'`
|
|
396
|
+
* — a legacy multi-model (or empty) chain earns no slot rows, so every
|
|
397
|
+
* surface fed by this resolver reports the inert state and routing stays on
|
|
398
|
+
* the raw `rootChain` (the v0.2.2 walk verbatim).
|
|
399
|
+
*/
|
|
400
|
+
function resolveSlotState(config, now, tz) {
|
|
401
|
+
if (!isAllDayConforming(config.rootChain)) return {
|
|
402
|
+
winner: "all-day",
|
|
403
|
+
label: "all-day"
|
|
404
|
+
};
|
|
405
|
+
const clock = wallClock(now, tz);
|
|
406
|
+
const seenPresets = /* @__PURE__ */ new Set();
|
|
407
|
+
const rows = Array.isArray(config.timeSlots) ? config.timeSlots : [];
|
|
408
|
+
for (const row of rows) {
|
|
409
|
+
if (typeof row !== "object" || row === null) {
|
|
410
|
+
warnMalformed(row, "row is not an object");
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
if (row.kind === "preset" && typeof row.preset === "string") {
|
|
414
|
+
if (seenPresets.has(row.preset)) {
|
|
415
|
+
warnMalformed(row, `duplicate preset "${row.preset}" — only the first row takes effect`);
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
seenPresets.add(row.preset);
|
|
419
|
+
}
|
|
420
|
+
const descriptor = describeRow(row);
|
|
421
|
+
if (descriptor === void 0) continue;
|
|
422
|
+
if (descriptor.complement ? !matchesAnyWindow(descriptor.windows, clock) : matchesAnyWindow(descriptor.windows, clock)) return {
|
|
423
|
+
winner: row,
|
|
424
|
+
label: labelOf(row)
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
winner: "all-day",
|
|
429
|
+
label: "all-day"
|
|
430
|
+
};
|
|
431
|
+
}
|
|
41
432
|
//#endregion
|
|
42
433
|
//#region src/config.ts
|
|
43
434
|
/**
|
|
@@ -64,7 +455,9 @@ window.__ModuleLoader__.load({
|
|
|
64
455
|
maxSwitchesPerStep: 8,
|
|
65
456
|
alwaysModeRetryCap: 5,
|
|
66
457
|
presets: "bundled",
|
|
67
|
-
roleAutoMatch: true
|
|
458
|
+
roleAutoMatch: true,
|
|
459
|
+
timeSlots: [],
|
|
460
|
+
tz: "Asia/Shanghai"
|
|
68
461
|
};
|
|
69
462
|
/**
|
|
70
463
|
* Reserved role id: legal as a rule target (`roles.rules[].role`) and as
|
|
@@ -84,7 +477,7 @@ window.__ModuleLoader__.load({
|
|
|
84
477
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
85
478
|
}
|
|
86
479
|
/**
|
|
87
|
-
* Read a nested value by path — the
|
|
480
|
+
* Read a nested value by path — the upstream `dsh-client-schema-form`
|
|
88
481
|
* `getPath` semantics, copied locally so the provider-configured join needs no
|
|
89
482
|
* new dependency (array indexes as numeric keys, `undefined` along a missing
|
|
90
483
|
* branch).
|
|
@@ -115,6 +508,15 @@ window.__ModuleLoader__.load({
|
|
|
115
508
|
return typeof entry.id === "string" && typeof entry.overridden === "boolean";
|
|
116
509
|
});
|
|
117
510
|
}
|
|
511
|
+
/** Seed-default persona from a revert-seed wire body (issue #59). */
|
|
512
|
+
function revertOutcomePersona(value) {
|
|
513
|
+
if (value === null || typeof value !== "object" || !("outcome" in value)) return void 0;
|
|
514
|
+
const outcome = value.outcome;
|
|
515
|
+
if (outcome === null || typeof outcome !== "object") return void 0;
|
|
516
|
+
if (!("reverted" in outcome) || outcome.reverted !== true) return void 0;
|
|
517
|
+
if (!("persona" in outcome) || typeof outcome.persona !== "string") return void 0;
|
|
518
|
+
return outcome.persona;
|
|
519
|
+
}
|
|
118
520
|
/**
|
|
119
521
|
* The provider dropdown's offer set (spec §2.5 D-4): catalog providers whose
|
|
120
522
|
* settings profile resolves in the describe namespaces — the Models page's
|
|
@@ -195,6 +597,23 @@ window.__ModuleLoader__.load({
|
|
|
195
597
|
if (enabled !== void 0 && typeof enabled !== "boolean") throw new TypeError("fallbacks descriptor enabled must be a boolean");
|
|
196
598
|
const roleAutoMatch = value.roleAutoMatch;
|
|
197
599
|
if (roleAutoMatch !== void 0 && typeof roleAutoMatch !== "boolean") throw new TypeError("fallbacks descriptor roleAutoMatch must be a boolean");
|
|
600
|
+
const timeSlots = value.timeSlots;
|
|
601
|
+
if (timeSlots !== void 0 && (!Array.isArray(timeSlots) || timeSlots.some((row) => {
|
|
602
|
+
if (!isRecord(row)) return true;
|
|
603
|
+
for (const field of [
|
|
604
|
+
"kind",
|
|
605
|
+
"preset",
|
|
606
|
+
"start",
|
|
607
|
+
"end"
|
|
608
|
+
]) if (row[field] !== void 0 && typeof row[field] !== "string") return true;
|
|
609
|
+
const chain = row.chain;
|
|
610
|
+
if (chain !== void 0 && (!Array.isArray(chain) || chain.some((entry) => typeof entry !== "string"))) return true;
|
|
611
|
+
const days = row.days;
|
|
612
|
+
if (days !== void 0 && (!Array.isArray(days) || days.some((day) => typeof day !== "number"))) return true;
|
|
613
|
+
return false;
|
|
614
|
+
}))) throw new TypeError("fallbacks descriptor timeSlots must be an array of slot rows (kind/preset/start/end strings, chain string array, days number array)");
|
|
615
|
+
const tz = value.tz;
|
|
616
|
+
if (tz !== void 0 && typeof tz !== "string") throw new TypeError("fallbacks descriptor tz must be a string");
|
|
198
617
|
return {
|
|
199
618
|
enabled: enabled ?? defaultFallbacksConfig.enabled,
|
|
200
619
|
triggerCodes: triggerCodes ?? [...defaultFallbacksConfig.triggerCodes],
|
|
@@ -208,7 +627,9 @@ window.__ModuleLoader__.load({
|
|
|
208
627
|
maxSwitchesPerStep: maxSwitchesPerStep ?? defaultFallbacksConfig.maxSwitchesPerStep,
|
|
209
628
|
alwaysModeRetryCap: alwaysModeRetryCap ?? defaultFallbacksConfig.alwaysModeRetryCap,
|
|
210
629
|
presets: presets ?? defaultFallbacksConfig.presets,
|
|
211
|
-
roleAutoMatch: roleAutoMatch ?? defaultFallbacksConfig.roleAutoMatch
|
|
630
|
+
roleAutoMatch: roleAutoMatch ?? defaultFallbacksConfig.roleAutoMatch,
|
|
631
|
+
timeSlots: timeSlots ?? [...defaultFallbacksConfig.timeSlots ?? []],
|
|
632
|
+
tz: tz ?? defaultFallbacksConfig.tz
|
|
212
633
|
};
|
|
213
634
|
}
|
|
214
635
|
/** The raw selector string a selection serializes to ('' when empty). */
|
|
@@ -310,13 +731,54 @@ window.__ModuleLoader__.load({
|
|
|
310
731
|
}
|
|
311
732
|
return entries;
|
|
312
733
|
}
|
|
734
|
+
/** Project the time-slot rows into editable rows (chain selectors classified). */
|
|
735
|
+
function timeSlotsToRows(timeSlots, catalog) {
|
|
736
|
+
return timeSlots.map((row) => ({
|
|
737
|
+
kind: row.kind,
|
|
738
|
+
...row.preset === void 0 ? {} : { preset: row.preset },
|
|
739
|
+
start: row.start ?? "",
|
|
740
|
+
end: row.end ?? "",
|
|
741
|
+
days: [...row.days ?? []],
|
|
742
|
+
name: row.name ?? "",
|
|
743
|
+
collapsed: true,
|
|
744
|
+
selectors: (row.chain ?? []).map((entry) => entryToSelectorRow(entry, catalog))
|
|
745
|
+
}));
|
|
746
|
+
}
|
|
747
|
+
/** Rebuild the time-slot rows from edited rows; blank selectors drop out.
|
|
748
|
+
* `kind` rides verbatim (a hand-written unknown kind reads back unchanged;
|
|
749
|
+
* save validation rejects it) — the cast asserts the trusted editor shape.
|
|
750
|
+
* `days` is ALWAYS serialized ([] included): schemastery composes absent
|
|
751
|
+
* array fields as `[]`, so the composed config every card load accepts
|
|
752
|
+
* carries `days` on every row — the draft must too, or a clean card would
|
|
753
|
+
* read back dirty. */
|
|
754
|
+
function rowsToTimeSlots(rows) {
|
|
755
|
+
return rows.map((row) => {
|
|
756
|
+
const chain = row.selectors.map(selectorRowToRaw).filter((entry) => entry !== "");
|
|
757
|
+
if (row.kind === "preset") return {
|
|
758
|
+
kind: "preset",
|
|
759
|
+
preset: row.preset,
|
|
760
|
+
days: row.days,
|
|
761
|
+
chain
|
|
762
|
+
};
|
|
763
|
+
return {
|
|
764
|
+
kind: row.kind,
|
|
765
|
+
...row.preset === void 0 ? {} : { preset: row.preset },
|
|
766
|
+
start: row.start,
|
|
767
|
+
end: row.end,
|
|
768
|
+
days: row.days,
|
|
769
|
+
...row.name === "" ? {} : { name: row.name },
|
|
770
|
+
chain
|
|
771
|
+
};
|
|
772
|
+
});
|
|
773
|
+
}
|
|
313
774
|
/** Project the declared roles into editable rows (chain selectors classified). */
|
|
314
775
|
function rolesToRows(roles, catalog) {
|
|
315
776
|
return roles.map((role) => ({
|
|
316
777
|
id: role.id,
|
|
317
778
|
persona: role.persona,
|
|
318
779
|
selectors: (role.chain ?? []).map((entry) => entryToSelectorRow(entry, catalog)),
|
|
319
|
-
fallback: role.fallback ?? "inherit-root"
|
|
780
|
+
fallback: role.fallback ?? "inherit-root",
|
|
781
|
+
collapsed: true
|
|
320
782
|
}));
|
|
321
783
|
}
|
|
322
784
|
/** Rebuild the declared roles from edited rows; empty selectors drop out. */
|
|
@@ -365,16 +827,14 @@ window.__ModuleLoader__.load({
|
|
|
365
827
|
/** Project the role rules into editable rows (provider/model classified). */
|
|
366
828
|
function rulesToRows(rules, catalog) {
|
|
367
829
|
return rules.map((rule) => ({
|
|
368
|
-
origin: rule.origin ?? "",
|
|
369
830
|
provider: classifyProvider(rule.provider ?? "", catalog),
|
|
370
831
|
model: classifyModel(rule.provider ?? "", rule.model ?? "", catalog),
|
|
371
832
|
role: rule.role
|
|
372
833
|
}));
|
|
373
834
|
}
|
|
374
|
-
/** Rebuild the role rules from edited rows; empty
|
|
835
|
+
/** Rebuild the role rules from edited rows; empty provider/model drop out. */
|
|
375
836
|
function rowsToRules(rows) {
|
|
376
837
|
return rows.map((row) => ({
|
|
377
|
-
...row.origin === "" ? {} : { origin: row.origin },
|
|
378
838
|
...row.provider === null ? {} : { provider: selectionToRaw(row.provider) },
|
|
379
839
|
...row.model === null ? {} : { model: selectionToRaw(row.model) },
|
|
380
840
|
role: row.role.trim()
|
|
@@ -658,12 +1118,17 @@ window.__ModuleLoader__.load({
|
|
|
658
1118
|
* reason }` outcome is still a successful RPC — the post-write read
|
|
659
1119
|
* result (config / legacyKeys / seeds) lands either way, and the revert
|
|
660
1120
|
* button stays disabled while the write is in flight.
|
|
1121
|
+
*
|
|
1122
|
+
* Returns the seed-default persona when the outcome is `{ reverted:
|
|
1123
|
+
* true, persona }` — including the persist no-op (persisted already
|
|
1124
|
+
* equals the seed). The card applies that string to the row's **draft**
|
|
1125
|
+
* so an unsaved persona edit still snaps back (issue #59).
|
|
661
1126
|
* @param id - the seeded role id; the host matches it by trimmed id
|
|
662
1127
|
* against the seed registry (spec §9.3).
|
|
663
1128
|
*/
|
|
664
1129
|
async revertSeed(id) {
|
|
665
1130
|
const state = this.store.getSnapshot();
|
|
666
|
-
if (!state.writable || state.status === "saving") return;
|
|
1131
|
+
if (!state.writable || state.status === "saving") return void 0;
|
|
667
1132
|
const generation = ++this.writeGeneration;
|
|
668
1133
|
this.store.update((draft) => {
|
|
669
1134
|
draft.status = "saving";
|
|
@@ -671,7 +1136,7 @@ window.__ModuleLoader__.load({
|
|
|
671
1136
|
});
|
|
672
1137
|
try {
|
|
673
1138
|
const result = await this.rpc.call("/api", "fallbacks/revert-seed", { args: { id } });
|
|
674
|
-
if (generation !== this.writeGeneration) return;
|
|
1139
|
+
if (generation !== this.writeGeneration) return void 0;
|
|
675
1140
|
if (!result.ok) throw result.error;
|
|
676
1141
|
const value = result.value;
|
|
677
1142
|
const config = value !== null && typeof value === "object" && "config" in value ? value.config : void 0;
|
|
@@ -686,9 +1151,11 @@ window.__ModuleLoader__.load({
|
|
|
686
1151
|
if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
|
|
687
1152
|
}
|
|
688
1153
|
this.accept(config, true, legacyKeys, seeds);
|
|
1154
|
+
return revertOutcomePersona(value);
|
|
689
1155
|
} catch (error) {
|
|
690
|
-
if (generation !== this.writeGeneration) return;
|
|
1156
|
+
if (generation !== this.writeGeneration) return void 0;
|
|
691
1157
|
this.fail(error);
|
|
1158
|
+
return;
|
|
692
1159
|
}
|
|
693
1160
|
}
|
|
694
1161
|
/** Stop in-flight responses from publishing after plugin disposal. */
|
|
@@ -817,16 +1284,62 @@ window.__ModuleLoader__.load({
|
|
|
817
1284
|
"roleAutoMatch.label": "启用角色自动匹配",
|
|
818
1285
|
"roleAutoMatch.hint": "规则未命中时,由模型自选最贴近的已声明角色",
|
|
819
1286
|
"roleAutoMatch.tooltip": "规则未命中时,模型会自动从已声明角色(id + persona)中选择最匹配者并注入该角色的链;关闭后未命中规则时按现状回落(inherit / rootChain)。",
|
|
820
|
-
"rootChain.label": "
|
|
821
|
-
"rootChain.
|
|
822
|
-
"
|
|
823
|
-
"rootChain.tooltip": "root 主代理失败时按此有序选择器列表依次降级;未配置时行为与未安装插件一致。",
|
|
824
|
-
"rootChain.selector.add": "添加选择器",
|
|
1287
|
+
"rootChain.label": "默认降级链",
|
|
1288
|
+
"rootChain.tooltip": "未命中任何分时槽时先走这条降级链;全部失败后落到下面的默认模型。",
|
|
1289
|
+
"defaultModel.label": "默认模型",
|
|
825
1290
|
"chains.selector.remove": "删除该选择器",
|
|
826
1291
|
"chains.selector.providerPlaceholder": "选择 provider",
|
|
827
1292
|
"chains.selector.modelPlaceholder": "选择 model",
|
|
828
1293
|
"chains.selector.wildcardLegacy": "该条目为通配(provider/*):选择具体模型后将转为精确条目",
|
|
829
1294
|
"chains.selector.noModelsStrict": "该 provider 暂无可用模型(目录查询失败),请改选其他 provider。",
|
|
1295
|
+
"mainAgent.label": "主代理",
|
|
1296
|
+
"subagents.label": "子代理",
|
|
1297
|
+
"timeSlots.label": "分时槽设置",
|
|
1298
|
+
"timeSlots.hint": "自上而下第一条命中生效;全时段行固定最后",
|
|
1299
|
+
"timeSlots.tz.label": "时区(UTC±)",
|
|
1300
|
+
"timeSlots.drag": "拖拽排序(或使用上下按钮)",
|
|
1301
|
+
"timeSlots.name": "名称",
|
|
1302
|
+
"timeSlots.expand": "展开该行",
|
|
1303
|
+
"timeSlots.collapse": "收起该行",
|
|
1304
|
+
"timeSlots.tooltip": "命中行的模型链成为 root 生效链(取代全时段链);未命中任何行时使用全时段链。分时切换是路由种子而非失败决策:不消耗冷却、不计入单步切换上限。",
|
|
1305
|
+
"timeSlots.addPreset": "添加预设",
|
|
1306
|
+
"timeSlots.addCustom": "添加自定义时段",
|
|
1307
|
+
"timeSlots.presetPlaceholder": "选择预设",
|
|
1308
|
+
"timeSlots.remove": "删除该时段行",
|
|
1309
|
+
"timeSlots.moveUp": "上移该时段行",
|
|
1310
|
+
"timeSlots.moveDown": "下移该时段行",
|
|
1311
|
+
"timeSlots.start": "开始(HH:mm)",
|
|
1312
|
+
"timeSlots.end": "结束(HH:mm)",
|
|
1313
|
+
"timeSlots.days": "星期",
|
|
1314
|
+
"timeSlots.days.hint": "不勾选 = 每天;可跨午夜",
|
|
1315
|
+
"timeSlots.preset.name": "预设",
|
|
1316
|
+
"timeSlots.preset.windowLabel": "时段(只读)",
|
|
1317
|
+
"timeSlots.preset.chainsOnly": "预设窗口已锁定:仅可编辑模型链",
|
|
1318
|
+
"timeSlots.preset.liang-peak.label": "梁文峰",
|
|
1319
|
+
"timeSlots.preset.liang-peak.window": "09:00–12:00 与 14:00–18:00(每天,UTC+8)",
|
|
1320
|
+
"timeSlots.preset.liang-valley.label": "梁文谷",
|
|
1321
|
+
"timeSlots.preset.liang-valley.window": "Liang Peak 之外的所有时间(每天,UTC+8)",
|
|
1322
|
+
"timeSlots.preset.glm-peak.label": "GLM峰",
|
|
1323
|
+
"timeSlots.preset.glm-peak.window": "周一至周五 14:00–18:00(UTC+8)",
|
|
1324
|
+
"timeSlots.preset.glm-valley.label": "GLM谷",
|
|
1325
|
+
"timeSlots.preset.glm-valley.window": "GLM Peak 之外的所有时间(UTC+8)",
|
|
1326
|
+
"timeSlots.preset.glm.note": "仅配置了 zai-coding-cn 时有效",
|
|
1327
|
+
"timeSlots.preset.highCost": "高消耗",
|
|
1328
|
+
"timeSlots.preset.multiplier": "x{n}",
|
|
1329
|
+
"timeSlots.active": "激活",
|
|
1330
|
+
"timeSlots.preset.glm.unconfigured": "(需配置 zai-coding-cn)",
|
|
1331
|
+
"timeSlots.day.sun": "日",
|
|
1332
|
+
"timeSlots.day.mon": "一",
|
|
1333
|
+
"timeSlots.day.tue": "二",
|
|
1334
|
+
"timeSlots.day.wed": "三",
|
|
1335
|
+
"timeSlots.day.thu": "四",
|
|
1336
|
+
"timeSlots.day.fri": "五",
|
|
1337
|
+
"timeSlots.day.sat": "六",
|
|
1338
|
+
"timeSlots.selector.add": "添加选择器",
|
|
1339
|
+
"allDay.hint": "全天链的最后一档兜底:官方 V4 Flash 或 V4 Pro 二选一",
|
|
1340
|
+
"allDay.flash": "官方 V4 Flash(deepseek-official/deepseek-v4-flash)",
|
|
1341
|
+
"allDay.pro": "官方 V4 Pro(deepseek-official/deepseek-v4-pro)",
|
|
1342
|
+
"allDay.nonconforming": "当前默认模型不合法:请选择官方 V4 Flash 或 V4 Pro 后保存",
|
|
830
1343
|
"roles.list.label": "角色实体",
|
|
831
1344
|
"roles.list.hint": "先声明角色,规则才能引用",
|
|
832
1345
|
"roles.list.tooltip": "角色 id 须匹配 /^[a-z0-9-]{1,32}$/ 且唯一;\"inherit\" 为保留字,不能用作角色 id。",
|
|
@@ -844,14 +1357,12 @@ window.__ModuleLoader__.load({
|
|
|
844
1357
|
"roles.fallback.none": "仅角色链(不追加 rootChain)",
|
|
845
1358
|
"roles.add": "添加角色",
|
|
846
1359
|
"roles.remove": "删除该角色",
|
|
1360
|
+
"roles.expand": "展开该角色",
|
|
1361
|
+
"roles.collapse": "收起该角色",
|
|
847
1362
|
"roles.selector.add": "添加选择器",
|
|
848
1363
|
"roles.rules": "角色规则",
|
|
849
|
-
"roles.rules.hint": "
|
|
850
|
-
"roles.rules.tooltip": "
|
|
851
|
-
"roles.rule.origin": "来源",
|
|
852
|
-
"roles.rule.origin.any": "任意",
|
|
853
|
-
"roles.rule.origin.root": "root",
|
|
854
|
-
"roles.rule.origin.subagent": "subagent",
|
|
1364
|
+
"roles.rules.hint": "仅对子代理生效:顺序匹配 provider/model,未命中 → inherit(root 链)",
|
|
1365
|
+
"roles.rules.tooltip": "规则仅对子代理生效(root 请求不匹配规则):命中后走对应角色的链;未命中走内置 inherit(rootChain)。",
|
|
855
1366
|
"roles.rule.provider": "provider",
|
|
856
1367
|
"roles.rule.provider.any": "任意",
|
|
857
1368
|
"roles.rule.model": "model",
|
|
@@ -869,6 +1380,14 @@ window.__ModuleLoader__.load({
|
|
|
869
1380
|
"validation.ruleRoleUndeclared": "规则引用了未声明的角色 \"{role}\"",
|
|
870
1381
|
"validation.ruleRoleRequired": "规则未选择角色:请选择目标角色,或删除该行",
|
|
871
1382
|
"validation.roleChainRequired": "角色 \"{id}\" 未配置模型:请至少添加一条链选择器(模型配置)",
|
|
1383
|
+
"validation.allDayRequired": "默认模型必须二选一:官方 V4 Flash 或 V4 Pro",
|
|
1384
|
+
"validation.slotChainRequired": "分时槽未配置模型:请至少添加一条链选择器",
|
|
1385
|
+
"validation.slotWindow": "分时槽开始/结束时间须为 HH:mm 格式",
|
|
1386
|
+
"validation.slotDays": "星期取值须为 0–6 的整数",
|
|
1387
|
+
"validation.slotKind": "分时槽 kind 须为 \"preset\" 或 \"custom\"",
|
|
1388
|
+
"validation.slotPresetUnknown": "未知的分时槽预设 \"{preset}\"",
|
|
1389
|
+
"validation.slotPresetDuplicate": "预设 \"{preset}\" 已存在:每个预设只能添加一行",
|
|
1390
|
+
"validation.slotPresetFrozen": "预设窗口是冻结代码常量:预设行不能携带 start/end/days",
|
|
872
1391
|
"validation.selector": "选择器 \"{entry}\" 非法:{message}",
|
|
873
1392
|
"legacy.banner": "检测到旧格式配置字段({keys}):已按新模型展示,请按 docs/configuration.md 迁移表手工改写;插件不会自动改写配置。",
|
|
874
1393
|
"catalog.empty": "暂无可用模型:请先在模型页添加模型,添加后此处将自动可选。",
|
|
@@ -905,12 +1424,6 @@ window.__ModuleLoader__.load({
|
|
|
905
1424
|
"save.saving": "保存中…",
|
|
906
1425
|
"save.error": "保存失败:{message}",
|
|
907
1426
|
"close": "关闭",
|
|
908
|
-
"reset": "恢复默认",
|
|
909
|
-
"reset.confirmTitle": "恢复默认配置",
|
|
910
|
-
"reset.confirm": "恢复后 fallbacks 配置将回到插件默认值,当前编辑内容会丢失。",
|
|
911
|
-
"reset.confirm.cancel": "取消",
|
|
912
|
-
"reset.confirm.action": "恢复默认",
|
|
913
|
-
"reset.saving": "恢复中…",
|
|
914
1427
|
"loading": "加载中…",
|
|
915
1428
|
"unavailable": "fallbacks 配置通道暂不可达:以下显示默认配置(或上次读取值),可尝试保存;保存失败会在此处如实提示。",
|
|
916
1429
|
"error.generic": "出错:{message}"
|
|
@@ -956,16 +1469,62 @@ window.__ModuleLoader__.load({
|
|
|
956
1469
|
"roleAutoMatch.label": "Enable role auto-match",
|
|
957
1470
|
"roleAutoMatch.hint": "On rules-miss, the model picks the closest declared role",
|
|
958
1471
|
"roleAutoMatch.tooltip": "When no rule matches, the model auto-selects the best-fit declared role (id + persona) and uses its chain; turn off to keep today's fallback (inherit / rootChain) on a rules-miss.",
|
|
959
|
-
"rootChain.label": "
|
|
960
|
-
"rootChain.
|
|
961
|
-
"
|
|
962
|
-
"rootChain.tooltip": "When the root agent fails it falls back down this ordered selector list; unset behaves like an uninstalled plugin.",
|
|
963
|
-
"rootChain.selector.add": "Add selector",
|
|
1472
|
+
"rootChain.label": "Default fallback chain",
|
|
1473
|
+
"rootChain.tooltip": "Walked first whenever no time slot matches; if every entry fails, the default model below is the last fallback.",
|
|
1474
|
+
"defaultModel.label": "Default model",
|
|
964
1475
|
"chains.selector.remove": "Remove this selector",
|
|
965
1476
|
"chains.selector.providerPlaceholder": "Select provider",
|
|
966
1477
|
"chains.selector.modelPlaceholder": "Select model",
|
|
967
1478
|
"chains.selector.wildcardLegacy": "This entry is a wildcard (provider/*): picking a model converts it to an exact entry",
|
|
968
1479
|
"chains.selector.noModelsStrict": "No models available for this provider (catalog lookup failed); pick another provider.",
|
|
1480
|
+
"mainAgent.label": "Main agent",
|
|
1481
|
+
"subagents.label": "Subagents",
|
|
1482
|
+
"timeSlots.label": "Time slots",
|
|
1483
|
+
"timeSlots.hint": "First match from top to bottom wins; the all-day row is always last",
|
|
1484
|
+
"timeSlots.tz.label": "Timezone (UTC±)",
|
|
1485
|
+
"timeSlots.drag": "Drag to reorder (or use the up/down buttons)",
|
|
1486
|
+
"timeSlots.name": "Name",
|
|
1487
|
+
"timeSlots.expand": "Expand this row",
|
|
1488
|
+
"timeSlots.collapse": "Collapse this row",
|
|
1489
|
+
"timeSlots.tooltip": "A matched row's model chain becomes the effective root chain (replacing the all-day chain); no match uses the all-day chain. A time-slot switch is a routing seed, not a failure decision: it consumes no cooldown and does not count against the per-step switch cap.",
|
|
1490
|
+
"timeSlots.addPreset": "Add preset",
|
|
1491
|
+
"timeSlots.addCustom": "Add custom time slot",
|
|
1492
|
+
"timeSlots.presetPlaceholder": "Select a preset",
|
|
1493
|
+
"timeSlots.remove": "Remove this time-slot row",
|
|
1494
|
+
"timeSlots.moveUp": "Move this time-slot row up",
|
|
1495
|
+
"timeSlots.moveDown": "Move this time-slot row down",
|
|
1496
|
+
"timeSlots.start": "Start (HH:mm)",
|
|
1497
|
+
"timeSlots.end": "End (HH:mm)",
|
|
1498
|
+
"timeSlots.days": "Days",
|
|
1499
|
+
"timeSlots.days.hint": "None selected = every day; may wrap midnight",
|
|
1500
|
+
"timeSlots.preset.name": "Preset",
|
|
1501
|
+
"timeSlots.preset.windowLabel": "Window (read-only)",
|
|
1502
|
+
"timeSlots.preset.chainsOnly": "Preset windows are frozen: only the model chain is editable",
|
|
1503
|
+
"timeSlots.preset.liang-peak.label": "Liang Peak",
|
|
1504
|
+
"timeSlots.preset.liang-peak.window": "09:00–12:00 & 14:00–18:00 (every day, UTC+8)",
|
|
1505
|
+
"timeSlots.preset.liang-valley.label": "Liang Valley",
|
|
1506
|
+
"timeSlots.preset.liang-valley.window": "All times outside Liang Peak (every day, UTC+8)",
|
|
1507
|
+
"timeSlots.preset.glm-peak.label": "GLM Peak",
|
|
1508
|
+
"timeSlots.preset.glm-peak.window": "Monday–Friday 14:00–18:00 (UTC+8)",
|
|
1509
|
+
"timeSlots.preset.glm-valley.label": "GLM Valley",
|
|
1510
|
+
"timeSlots.preset.glm-valley.window": "All times outside GLM Peak (UTC+8)",
|
|
1511
|
+
"timeSlots.preset.glm.note": "Only effective when zai-coding-cn is configured",
|
|
1512
|
+
"timeSlots.preset.highCost": "High Cost",
|
|
1513
|
+
"timeSlots.preset.multiplier": "x{n}",
|
|
1514
|
+
"timeSlots.active": "Active",
|
|
1515
|
+
"timeSlots.preset.glm.unconfigured": " (requires zai-coding-cn)",
|
|
1516
|
+
"timeSlots.day.sun": "Sun",
|
|
1517
|
+
"timeSlots.day.mon": "Mon",
|
|
1518
|
+
"timeSlots.day.tue": "Tue",
|
|
1519
|
+
"timeSlots.day.wed": "Wed",
|
|
1520
|
+
"timeSlots.day.thu": "Thu",
|
|
1521
|
+
"timeSlots.day.fri": "Fri",
|
|
1522
|
+
"timeSlots.day.sat": "Sat",
|
|
1523
|
+
"timeSlots.selector.add": "Add selector",
|
|
1524
|
+
"allDay.hint": "Last-resort fallback of the all-day chain: official V4 Flash or Pro (pick exactly one)",
|
|
1525
|
+
"allDay.flash": "Official V4 Flash (deepseek-official/deepseek-v4-flash)",
|
|
1526
|
+
"allDay.pro": "Official V4 Pro (deepseek-official/deepseek-v4-pro)",
|
|
1527
|
+
"allDay.nonconforming": "The current default model is not valid: pick official V4 Flash or Pro before saving",
|
|
969
1528
|
"roles.list.label": "Declared roles",
|
|
970
1529
|
"roles.list.hint": "Declare roles before rules can reference them",
|
|
971
1530
|
"roles.list.tooltip": "Role ids must match /^[a-z0-9-]{1,32}$/ and be unique; \"inherit\" is reserved and cannot be used as a role id.",
|
|
@@ -983,14 +1542,12 @@ window.__ModuleLoader__.load({
|
|
|
983
1542
|
"roles.fallback.none": "Role chain only (no rootChain)",
|
|
984
1543
|
"roles.add": "Add role",
|
|
985
1544
|
"roles.remove": "Remove this role",
|
|
1545
|
+
"roles.expand": "Expand this role",
|
|
1546
|
+
"roles.collapse": "Collapse this role",
|
|
986
1547
|
"roles.selector.add": "Add selector",
|
|
987
1548
|
"roles.rules": "Role rules",
|
|
988
|
-
"roles.rules.hint": "
|
|
989
|
-
"roles.rules.tooltip": "
|
|
990
|
-
"roles.rule.origin": "Origin",
|
|
991
|
-
"roles.rule.origin.any": "Any",
|
|
992
|
-
"roles.rule.origin.root": "root",
|
|
993
|
-
"roles.rule.origin.subagent": "subagent",
|
|
1549
|
+
"roles.rules.hint": "Subagents only: matches provider/model in order; no match → inherit (root chain)",
|
|
1550
|
+
"roles.rules.tooltip": "Rules apply to subagents only (root requests never match): a matched rule uses that role's chain; no match uses the built-in inherit (rootChain).",
|
|
994
1551
|
"roles.rule.provider": "provider",
|
|
995
1552
|
"roles.rule.provider.any": "Any",
|
|
996
1553
|
"roles.rule.model": "model",
|
|
@@ -1008,6 +1565,14 @@ window.__ModuleLoader__.load({
|
|
|
1008
1565
|
"validation.ruleRoleUndeclared": "Rule references undeclared role \"{role}\"",
|
|
1009
1566
|
"validation.ruleRoleRequired": "Rule has no role selected: pick a target role, or remove the row",
|
|
1010
1567
|
"validation.roleChainRequired": "Role \"{id}\" has no model config: add at least one chain entry",
|
|
1568
|
+
"validation.allDayRequired": "The default model must be exactly one official V4 model (V4 Flash or V4 Pro)",
|
|
1569
|
+
"validation.slotChainRequired": "Time-slot row has no models: add at least one chain entry",
|
|
1570
|
+
"validation.slotWindow": "Time-slot start/end must use HH:mm format",
|
|
1571
|
+
"validation.slotDays": "Days must be integers 0–6",
|
|
1572
|
+
"validation.slotKind": "Time-slot kind must be \"preset\" or \"custom\"",
|
|
1573
|
+
"validation.slotPresetUnknown": "Unknown time-slot preset \"{preset}\"",
|
|
1574
|
+
"validation.slotPresetDuplicate": "Preset \"{preset}\" already exists: at most one row per preset",
|
|
1575
|
+
"validation.slotPresetFrozen": "Preset windows are frozen code constants: a preset row cannot carry start/end/days",
|
|
1011
1576
|
"validation.selector": "Invalid selector \"{entry}\": {message}",
|
|
1012
1577
|
"legacy.banner": "Legacy config fields detected ({keys}): now shown in the new model — rewrite them manually following the migration table in docs/configuration.md (the plugin will not rewrite them automatically).",
|
|
1013
1578
|
"catalog.empty": "No models yet: add a model on the Models page first; options will appear here automatically.",
|
|
@@ -1044,12 +1609,6 @@ window.__ModuleLoader__.load({
|
|
|
1044
1609
|
"save.saving": "Saving…",
|
|
1045
1610
|
"save.error": "Save failed: {message}",
|
|
1046
1611
|
"close": "Close",
|
|
1047
|
-
"reset": "Reset to defaults",
|
|
1048
|
-
"reset.confirmTitle": "Reset to defaults",
|
|
1049
|
-
"reset.confirm": "Resetting restores the fallbacks configuration to plugin defaults; your current edits will be lost.",
|
|
1050
|
-
"reset.confirm.cancel": "Cancel",
|
|
1051
|
-
"reset.confirm.action": "Reset",
|
|
1052
|
-
"reset.saving": "Resetting…",
|
|
1053
1612
|
"loading": "Loading…",
|
|
1054
1613
|
"unavailable": "The fallbacks config channel is unreachable: showing the default configuration (or the last read value). You can try to save; failures will be reported here.",
|
|
1055
1614
|
"error.generic": "Error: {message}"
|
|
@@ -1092,7 +1651,7 @@ window.__ModuleLoader__.load({
|
|
|
1092
1651
|
}
|
|
1093
1652
|
//#endregion
|
|
1094
1653
|
//#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/FallbacksCard.module.css.mjs
|
|
1095
|
-
const css$2 = "\n\n\n._8827595f_card {\n list-style: none;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n\n._8827595f_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._06704203_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._e488d460_header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n\n._e488d460_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n\n._f5dfe084_headText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n._8d39bde6_name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n\n._346f3b69_description {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._631094a0_chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n\n._44836ce8_chevronOpen {\n transform: rotate(180deg);\n}\n\n\n._dbaa7975_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding-bottom: 8px;\n}\n\n._4e39cf17_readOnly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._99bf7f3c_pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n\n._114985b2_footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 0 4px;\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n\n\n._9860a5b1_notice {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n\n._5006d43e_legacyNotice {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n._21918751_error {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._7cea4b2f_noticeRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 12px 0 0;\n}\n\n._7cea4b2f_noticeRow ._21918751_error {\n flex: 1;\n min-width: 0;\n margin: 0;\n}\n\n\n._4058c747_form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 0 0;\n}\n\n\n._9998065c_checkboxRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._02c2f6df_checkLabel {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 14px;\n line-height: 22px;\n font-weight: 400;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._f2d47237_checkLabelTitle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-weight: 400;\n}\n\n._c1bed8ea_checkLabelDesc {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._06389b18_checkbox {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._94c91bfd_fieldset {\n margin: 0;\n padding: 0;\n border: none;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n\n._67826267_field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n}\n\n._13e68c3f_fieldLabel {\n \n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._b116c758_sectionToggle {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n._b116c758_sectionToggle:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n\n._b116c758_sectionToggle:disabled {\n cursor: default;\n}\n\n._b116c758_sectionToggle:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 6px;\n}\n\n._a5313fdf_sectionToggleText {\n flex: 1;\n min-width: 0;\n text-align: left;\n}\n\n._4bc809b8_hint {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._579f813a_defaultNote {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._a6244318_infoHint {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n font-size: 14px;\n line-height: 1;\n color: var(--dsw-alias-label-tertiary);\n background: var(--dsw-alias-interactive-bg-hover);\n cursor: help;\n user-select: none;\n}\n\n._a6244318_infoHint:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._e655c840_infoHintDisabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._a2521bb0_optionRow {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._a2521bb0_optionRow:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n\n._06389b18_checkbox,\n._a2521bb0_optionRow input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:focus-visible,\n._a2521bb0_optionRow input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._a2521bb0_optionRow input:disabled {\n cursor: default;\n}\n\n\n._f9d86f7b_input {\n box-sizing: border-box;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n}\n\n._f9d86f7b_input:focus {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n\n._f9d86f7b_input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n._f9d86f7b_input:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n\n._3a9b42fd_inputTextarea {\n height: auto;\n min-height: 72px;\n padding: 6px 10px;\n resize: vertical;\n line-height: 20px;\n}\n\n\n._7b60337a_inputInvalid,\n._7b60337a_inputInvalid:focus {\n border-color: var(--dsw-alias-state-error-primary);\n}\n\n\nselect._f9d86f7b_input {\n max-width: 240px;\n cursor: pointer;\n}\n\n\n._16eb7153_selectInput {\n appearance: none;\n padding-right: 32px;\n \n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n background-size: 12px 12px;\n}\n\n\n._3e95886d_numberFields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n}\n\n._0cfb5881_list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n\n._f5c620d6_editorCard {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n}\n\n._224b1387_cardFoot {\n display: flex;\n justify-content: flex-end;\n}\n\n._8e220e07_ruleGrid {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n._24a12a2f_ruleCell {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 120px;\n flex: 1;\n}\n\n._1014c097_ruleCellLabel {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._15a12620_chainSelectors {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n._240cbbf8_selectorRow {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n\n._70effa64_iconButton {\n position: relative;\n box-sizing: border-box;\n appearance: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 6px;\n background: none;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n._70effa64_iconButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._70effa64_iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._70effa64_iconButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._70effa64_iconButton::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%);\n padding: 3px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n font-size: 11px;\n line-height: 17px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity .12s;\n}\n\n._70effa64_iconButton:hover::after,\n._70effa64_iconButton:focus-visible::after {\n opacity: 1;\n}\n\n\n._a0968257_iconButtonDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._28202c90_addButton {\n align-self: flex-start;\n}\n\n\n._747fd56d_primaryButton,\n._7e855445_secondaryButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n._747fd56d_primaryButton {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n._747fd56d_primaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n._7e855445_secondaryButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n\n._7e855445_secondaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n\n._747fd56d_primaryButton:disabled,\n._7e855445_secondaryButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._747fd56d_primaryButton:focus-visible,\n._7e855445_secondaryButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._fbd045e0_statusBlock {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 14px;\n margin-top: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n}\n\n._d4f70367_statusTitle {\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._8ab300ed_statusLine {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._e8cedbf5_statusLineLabel {\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._b48dfcba_offNotice {\n margin: 0;\n padding: 12px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 8px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n\n._ec8bd970_resetDialog {\n width: min(480px, 100%);\n}\n\n._8677165c_confirmDanger:not(:disabled) {\n border-color: var(--dsw-alias-state-error-primary);\n color: var(--dsw-alias-state-error-primary);\n}\n\n._8677165c_confirmDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._70effa64_iconButton::after {\n transition: none;\n }\n}\n";
|
|
1654
|
+
const css$2 = "\n\n\n._8827595f_card {\n list-style: none;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n\n._8827595f_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._06704203_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._e488d460_header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n\n._e488d460_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n\n._f5dfe084_headText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n._8d39bde6_name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n\n._346f3b69_description {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._631094a0_chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n\n._44836ce8_chevronOpen {\n transform: rotate(180deg);\n}\n\n\n._dbaa7975_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding-bottom: 8px;\n}\n\n._4e39cf17_readOnly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._99bf7f3c_pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n\n\n\n\n._9860a5b1_notice {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n\n._5006d43e_legacyNotice {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n._21918751_error {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._7cea4b2f_noticeRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 12px 0 0;\n}\n\n._7cea4b2f_noticeRow ._21918751_error {\n flex: 1;\n min-width: 0;\n margin: 0;\n}\n\n\n._4058c747_form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 0 0;\n}\n\n\n._9998065c_checkboxRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._02c2f6df_checkLabel {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 14px;\n line-height: 22px;\n font-weight: 400;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._f2d47237_checkLabelTitle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-weight: 400;\n}\n\n._c1bed8ea_checkLabelDesc {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._06389b18_checkbox {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._94c91bfd_fieldset {\n margin: 0;\n padding: 0;\n border: none;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n\n._67826267_field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n}\n\n._13e68c3f_fieldLabel {\n \n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._ba240d82_sectionHeading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n._ddbc1b49_sectionHeadingText {\n flex: 1;\n min-width: 0;\n}\n\n\n._c41f9db7_sectionActions {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n}\n\n\n._b116c758_sectionToggle {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n._b116c758_sectionToggle:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n\n._b116c758_sectionToggle:disabled {\n cursor: default;\n}\n\n._b116c758_sectionToggle:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 6px;\n}\n\n._a5313fdf_sectionToggleText {\n flex: 1;\n min-width: 0;\n text-align: left;\n}\n\n._4bc809b8_hint {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._579f813a_defaultNote {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._b1962759_slotPresetName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._a6244318_infoHint {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n font-size: 14px;\n line-height: 1;\n color: var(--dsw-alias-label-tertiary);\n background: var(--dsw-alias-interactive-bg-hover);\n cursor: help;\n user-select: none;\n}\n\n._a6244318_infoHint:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._e655c840_infoHintDisabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._a2521bb0_optionRow {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._a2521bb0_optionRow:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n\n._06389b18_checkbox,\n._a2521bb0_optionRow input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:focus-visible,\n._a2521bb0_optionRow input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._a2521bb0_optionRow input:disabled {\n cursor: default;\n}\n\n\n._c4ecbdf3_dayRow {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n._0330c1ed_dayCell {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n border-radius: 6px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n._0330c1ed_dayCell input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell input:disabled {\n cursor: default;\n}\n\n._0330c1ed_dayCell input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._f9d86f7b_input {\n box-sizing: border-box;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n}\n\n._f9d86f7b_input:focus {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n\n._f9d86f7b_input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n._f9d86f7b_input:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n\n._3a9b42fd_inputTextarea {\n height: auto;\n min-height: 72px;\n padding: 6px 10px;\n resize: vertical;\n line-height: 20px;\n}\n\n\n._7b60337a_inputInvalid,\n._7b60337a_inputInvalid:focus {\n border-color: var(--dsw-alias-state-error-primary);\n}\n\n\nselect._f9d86f7b_input {\n max-width: 240px;\n cursor: pointer;\n}\n\n\n._16eb7153_selectInput {\n appearance: none;\n padding-right: 32px;\n \n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n background-size: 12px 12px;\n}\n\n\n._3e95886d_numberFields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n}\n\n._0cfb5881_list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n\n._f5c620d6_editorCard {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n}\n\n._224b1387_cardFoot {\n display: flex;\n justify-content: flex-end;\n}\n\n._8e220e07_ruleGrid {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n._24a12a2f_ruleCell {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 120px;\n flex: 1;\n}\n\n\n._86bc52d2_collapseRow {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n._a73efcc6_collapseToggle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n font: inherit;\n text-align: left;\n}\n\n._a73efcc6_collapseToggle:disabled {\n cursor: default;\n}\n\n._af017718_collapseTitle {\n \n flex: none;\n max-width: 55%;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n._2cabe603_collapseMeta {\n \n flex: none;\n margin-left: auto;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n._7b04f727_slotTag {\n flex: none;\n display: inline-flex;\n align-items: center;\n border-radius: 999px;\n padding: 0 6px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n border: 1px solid;\n}\n\n._c381e792_slotTagHighCost {\n color: var(--dsw-alias-state-error-primary);\n border-color: var(--dsw-alias-state-error-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n._23bdb6fc_slotTagMultiplier {\n color: var(--dsw-alias-state-warn-primary);\n border-color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 10%, transparent);\n}\n\n._f000eed9_slotTagActive {\n color: var(--dsw-alias-state-success-primary);\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent);\n}\n\n\n._cd905ce5_dragHandle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: grab;\n color: var(--dsw-alias-label-tertiary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 6px;\n flex: none;\n}\n\n._cd905ce5_dragHandle:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._cd905ce5_dragHandle:active {\n cursor: grabbing;\n}\n\n._cd905ce5_dragHandle:disabled {\n cursor: default;\n opacity: 0.4;\n}\n\n._cd905ce5_dragHandle:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._49f0c4f0_dragHandleIcon {\n transform: rotate(90deg);\n}\n\n\n._fee63b7e_slotCardDragging {\n opacity: 0.45;\n}\n\n._6f108491_slotCardOver {\n outline: 1px dashed var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n._1014c097_ruleCellLabel {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._15a12620_chainSelectors {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n._240cbbf8_selectorRow {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n\n._70effa64_iconButton {\n position: relative;\n box-sizing: border-box;\n appearance: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 6px;\n background: none;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n._70effa64_iconButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._70effa64_iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._70effa64_iconButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._70effa64_iconButton::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%);\n padding: 3px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n font-size: 11px;\n line-height: 17px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity .12s;\n}\n\n._70effa64_iconButton:hover::after,\n._70effa64_iconButton:focus-visible::after {\n opacity: 1;\n}\n\n\n._a0968257_iconButtonDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._28202c90_addButton {\n align-self: flex-start;\n}\n\n\n._6a2bd54c_slotAddRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n flex-wrap: wrap;\n}\n\n\n._4e77523e_rowActions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n\n._747fd56d_primaryButton,\n._7e855445_secondaryButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n._747fd56d_primaryButton {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n._747fd56d_primaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n._7e855445_secondaryButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n\n._7e855445_secondaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n\n._747fd56d_primaryButton:disabled,\n._7e855445_secondaryButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._747fd56d_primaryButton:focus-visible,\n._7e855445_secondaryButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._238d19be_sectionAction {\n height: 28px;\n padding: 0 12px;\n border-radius: 14px;\n font-size: 12px;\n line-height: 18px;\n}\n\n\n._fbd045e0_statusBlock {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 14px;\n margin-top: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n}\n\n._d4f70367_statusTitle {\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._8ab300ed_statusLine {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._e8cedbf5_statusLineLabel {\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._b48dfcba_offNotice {\n margin: 0;\n padding: 12px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 8px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._70effa64_iconButton::after {\n transition: none;\n }\n}\n";
|
|
1096
1655
|
const tagId$2 = "dsh-llm-fallbacks/FallbacksCard.module.css";
|
|
1097
1656
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
1098
1657
|
const tag = document.createElement("style");
|
|
@@ -1113,7 +1672,6 @@ window.__ModuleLoader__.load({
|
|
|
1113
1672
|
"body": "_dbaa7975_body",
|
|
1114
1673
|
"readOnly": "_4e39cf17_readOnly",
|
|
1115
1674
|
"pending": "_99bf7f3c_pending",
|
|
1116
|
-
"footer": "_114985b2_footer",
|
|
1117
1675
|
"notice": "_9860a5b1_notice",
|
|
1118
1676
|
"legacyNotice": "_5006d43e_legacyNotice",
|
|
1119
1677
|
"error": "_21918751_error",
|
|
@@ -1127,13 +1685,19 @@ window.__ModuleLoader__.load({
|
|
|
1127
1685
|
"fieldset": "_94c91bfd_fieldset",
|
|
1128
1686
|
"field": "_67826267_field",
|
|
1129
1687
|
"fieldLabel": "_13e68c3f_fieldLabel",
|
|
1688
|
+
"sectionHeading": "_ba240d82_sectionHeading",
|
|
1689
|
+
"sectionHeadingText": "_ddbc1b49_sectionHeadingText",
|
|
1690
|
+
"sectionActions": "_c41f9db7_sectionActions",
|
|
1130
1691
|
"sectionToggle": "_b116c758_sectionToggle",
|
|
1131
1692
|
"sectionToggleText": "_a5313fdf_sectionToggleText",
|
|
1132
1693
|
"hint": "_4bc809b8_hint",
|
|
1133
1694
|
"defaultNote": "_579f813a_defaultNote",
|
|
1695
|
+
"slotPresetName": "_b1962759_slotPresetName",
|
|
1134
1696
|
"infoHint": "_a6244318_infoHint",
|
|
1135
1697
|
"infoHintDisabled": "_e655c840_infoHintDisabled",
|
|
1136
1698
|
"optionRow": "_a2521bb0_optionRow",
|
|
1699
|
+
"dayRow": "_c4ecbdf3_dayRow",
|
|
1700
|
+
"dayCell": "_0330c1ed_dayCell",
|
|
1137
1701
|
"input": "_f9d86f7b_input",
|
|
1138
1702
|
"inputTextarea": "_3a9b42fd_inputTextarea",
|
|
1139
1703
|
"inputInvalid": "_7b60337a_inputInvalid",
|
|
@@ -1144,21 +1708,34 @@ window.__ModuleLoader__.load({
|
|
|
1144
1708
|
"cardFoot": "_224b1387_cardFoot",
|
|
1145
1709
|
"ruleGrid": "_8e220e07_ruleGrid",
|
|
1146
1710
|
"ruleCell": "_24a12a2f_ruleCell",
|
|
1711
|
+
"collapseRow": "_86bc52d2_collapseRow",
|
|
1712
|
+
"collapseToggle": "_a73efcc6_collapseToggle",
|
|
1713
|
+
"collapseTitle": "_af017718_collapseTitle",
|
|
1714
|
+
"collapseMeta": "_2cabe603_collapseMeta",
|
|
1715
|
+
"slotTag": "_7b04f727_slotTag",
|
|
1716
|
+
"slotTagHighCost": "_c381e792_slotTagHighCost",
|
|
1717
|
+
"slotTagMultiplier": "_23bdb6fc_slotTagMultiplier",
|
|
1718
|
+
"slotTagActive": "_f000eed9_slotTagActive",
|
|
1719
|
+
"dragHandle": "_cd905ce5_dragHandle",
|
|
1720
|
+
"dragHandleIcon": "_49f0c4f0_dragHandleIcon",
|
|
1721
|
+
"slotCardDragging": "_fee63b7e_slotCardDragging",
|
|
1722
|
+
"slotCardOver": "_6f108491_slotCardOver",
|
|
1147
1723
|
"ruleCellLabel": "_1014c097_ruleCellLabel",
|
|
1148
1724
|
"chainSelectors": "_15a12620_chainSelectors",
|
|
1149
1725
|
"selectorRow": "_240cbbf8_selectorRow",
|
|
1150
1726
|
"iconButton": "_70effa64_iconButton",
|
|
1151
1727
|
"iconButtonDanger": "_a0968257_iconButtonDanger",
|
|
1152
1728
|
"addButton": "_28202c90_addButton",
|
|
1729
|
+
"slotAddRow": "_6a2bd54c_slotAddRow",
|
|
1730
|
+
"rowActions": "_4e77523e_rowActions",
|
|
1153
1731
|
"primaryButton": "_747fd56d_primaryButton",
|
|
1154
1732
|
"secondaryButton": "_7e855445_secondaryButton",
|
|
1733
|
+
"sectionAction": "_238d19be_sectionAction",
|
|
1155
1734
|
"statusBlock": "_fbd045e0_statusBlock",
|
|
1156
1735
|
"statusTitle": "_d4f70367_statusTitle",
|
|
1157
1736
|
"statusLine": "_8ab300ed_statusLine",
|
|
1158
1737
|
"statusLineLabel": "_e8cedbf5_statusLineLabel",
|
|
1159
|
-
"offNotice": "_b48dfcba_offNotice"
|
|
1160
|
-
"resetDialog": "_ec8bd970_resetDialog",
|
|
1161
|
-
"confirmDanger": "_8677165c_confirmDanger"
|
|
1738
|
+
"offNotice": "_b48dfcba_offNotice"
|
|
1162
1739
|
};
|
|
1163
1740
|
//#endregion
|
|
1164
1741
|
//#region src/client/FallbacksCard.tsx
|
|
@@ -1176,12 +1753,22 @@ window.__ModuleLoader__.load({
|
|
|
1176
1753
|
* description, with a dirty "unsaved" pill and a rotating chevron
|
|
1177
1754
|
* (`IconChevronDownOutline14` from ui-primitives — a CLIENT_EXTERNALS value
|
|
1178
1755
|
* import), `aria-expanded`/`aria-label` like the upstream header; a divider
|
|
1179
|
-
* under the header; then the form content
|
|
1180
|
-
*
|
|
1181
|
-
*
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
* (
|
|
1756
|
+
* under the header; then the form content. PR #62 UX round 2: the card
|
|
1757
|
+
* footer is gone — each big section (主代理 / 子代理 / 高级选项) carries its
|
|
1758
|
+
* own Save/Discard actions beside its heading (高级选项: inside the expanded
|
|
1759
|
+
* body) and its own validation / save-error surface. PR #62 UX round 3:
|
|
1760
|
+
* each section's Save writes ONLY that section's fields — 主代理 owns
|
|
1761
|
+
* rootChain / timeSlots / tz (+ the card-level `enabled`), 子代理 owns
|
|
1762
|
+
* roles, 高级选项 owns the advanced scalars; the patch spreads the last
|
|
1763
|
+
* ACCEPTED config for every other section, so a 主代理 Save can never
|
|
1764
|
+
* ride along an unsaved 子代理 edit (and vice versa) — and validation /
|
|
1765
|
+
* the dirty gate apply per section too (a bad role id never blocks 主代理,
|
|
1766
|
+
* and only the saved section's Discard reverts that section's edits).
|
|
1767
|
+
* Save/discard disabled terms: save = `!sectionDirty || saving ||
|
|
1768
|
+
* !writable`, discard = `!sectionDirty || saving` (KD-U1). Disclosure is
|
|
1769
|
+
* card-local state:
|
|
1770
|
+
* which card a user has open is a reading gesture, and staged edits outlive
|
|
1771
|
+
* collapsing — the pill rides the header (upstream rationale).
|
|
1185
1772
|
*
|
|
1186
1773
|
* The form body is the two-block editing surface (spec §8): the `enabled`
|
|
1187
1774
|
* checkbox row, the 6 top-level scalar fields (trigger codes / revert
|
|
@@ -1197,13 +1784,14 @@ window.__ModuleLoader__.load({
|
|
|
1197
1784
|
* non-empty `state.legacyKeys` renders the migration banner at the top of
|
|
1198
1785
|
* the card body. The row editors keep their filled editorCard surface
|
|
1199
1786
|
* inside the card, with `--dsw-alias-*` tokens throughout. The reset-
|
|
1200
|
-
* to-defaults
|
|
1201
|
-
* the
|
|
1787
|
+
* to-defaults affordance is GONE from the card (PR #62 UX round 3) — the
|
|
1788
|
+
* gateway RPC `fallbacks/reset` and the store `resetToDefaults()` stay as
|
|
1789
|
+
* host APIs (store/gateway tests unchanged), only the card UI was removed.
|
|
1202
1790
|
*
|
|
1203
1791
|
* The page-only chrome is gone (720px column wrapper, title/intro banners,
|
|
1204
1792
|
* page-bottom status block): the AC-7 read-only status (derived effective
|
|
1205
|
-
* model + recent-switch summary) is folded into the card body
|
|
1206
|
-
*
|
|
1793
|
+
* model + recent-switch summary) is folded into the card body, and the
|
|
1794
|
+
* plugin-config section owns the column width.
|
|
1207
1795
|
*
|
|
1208
1796
|
* Degraded/error/loading states keep the same card chrome (KD-U3): the
|
|
1209
1797
|
* header always renders title+description+chevron, and the body carries the
|
|
@@ -1217,8 +1805,11 @@ window.__ModuleLoader__.load({
|
|
|
1217
1805
|
* 'error'`) also forces the body open with an error notice and — when the
|
|
1218
1806
|
* form is inert (`!writable`, i.e. the load never landed) — a Retry button;
|
|
1219
1807
|
* a save failure keeps the editable form so the Save action itself is the
|
|
1220
|
-
* retry
|
|
1221
|
-
*
|
|
1808
|
+
* retry. PR #62 UX round 2: the single `state.error` surface is split by
|
|
1809
|
+
* origin — a LOAD failure keeps the card-top notice (with Retry when
|
|
1810
|
+
* inert), while a WRITE failure renders under the section whose Save was
|
|
1811
|
+
* last clicked (`lastSaveSection`), unlike the advisor's separate
|
|
1812
|
+
* apply-failure hints.
|
|
1222
1813
|
*
|
|
1223
1814
|
* The degraded derivation is latched in the card (the store stays untouched):
|
|
1224
1815
|
* `present` only ever changes inside the store's `accept()`, so the settled
|
|
@@ -1228,6 +1819,77 @@ window.__ModuleLoader__.load({
|
|
|
1228
1819
|
* implemented without a store change); on a first mount the latch is false,
|
|
1229
1820
|
* so the healthy card starts (and stays) collapsed through its first load.
|
|
1230
1821
|
*/
|
|
1822
|
+
const ALL_DAY_FLASH = "deepseek-official/deepseek-v4-flash";
|
|
1823
|
+
const ALL_DAY_PRO = "deepseek-official/deepseek-v4-pro";
|
|
1824
|
+
const SLOT_PRESET_IDS = [
|
|
1825
|
+
"liang-peak",
|
|
1826
|
+
"liang-valley",
|
|
1827
|
+
"glm-peak",
|
|
1828
|
+
"glm-valley"
|
|
1829
|
+
];
|
|
1830
|
+
/** Custom-row day toggle order (index = weekday, 0=Sunday); display copy lives in the dictionaries. */
|
|
1831
|
+
const SLOT_WEEKDAYS = [
|
|
1832
|
+
"sun",
|
|
1833
|
+
"mon",
|
|
1834
|
+
"tue",
|
|
1835
|
+
"wed",
|
|
1836
|
+
"thu",
|
|
1837
|
+
"fri",
|
|
1838
|
+
"sat"
|
|
1839
|
+
];
|
|
1840
|
+
/** IANA timezone of this renderer (browser / host). */
|
|
1841
|
+
function hostTimeZone() {
|
|
1842
|
+
try {
|
|
1843
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
1844
|
+
return typeof tz === "string" && tz !== "" ? tz : "UTC";
|
|
1845
|
+
} catch {
|
|
1846
|
+
return "UTC";
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
/** `UTC+8` / `UTC-4` for an IANA id (current offset, DST-honest). */
|
|
1850
|
+
function tzUtcOffset(tz) {
|
|
1851
|
+
try {
|
|
1852
|
+
const name = new Intl.DateTimeFormat("en-US", {
|
|
1853
|
+
timeZone: tz,
|
|
1854
|
+
timeZoneName: "shortOffset"
|
|
1855
|
+
}).formatToParts(/* @__PURE__ */ new Date()).find((part) => part.type === "timeZoneName")?.value;
|
|
1856
|
+
if (name === void 0 || name === "") return "";
|
|
1857
|
+
return name.replace(/^GMT/, "UTC");
|
|
1858
|
+
} catch {
|
|
1859
|
+
return "";
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
/** Read-only custom-row copy: `Asia/Shanghai (UTC+8)`. */
|
|
1863
|
+
function tzDisplayLabel(tz) {
|
|
1864
|
+
const offset = tzUtcOffset(tz);
|
|
1865
|
+
return offset === "" ? tz : `${tz} (${offset})`;
|
|
1866
|
+
}
|
|
1867
|
+
/** Persist tz: presets lock UTC+8; custom-only uses the host zone; else keep the accepted value. */
|
|
1868
|
+
function resolvedSlotTz(rows, fallback) {
|
|
1869
|
+
if (rows.some((row) => row.kind === "preset")) return "Asia/Shanghai";
|
|
1870
|
+
if (rows.some((row) => row.kind === "custom")) return hostTimeZone();
|
|
1871
|
+
return fallback === "" ? "Asia/Shanghai" : fallback;
|
|
1872
|
+
}
|
|
1873
|
+
/** Strict 24h `HH:mm` — the resolver's HHMM_RE twin (drift-guarded by the gateway reject-on-save). */
|
|
1874
|
+
const HHMM_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
1875
|
+
/**
|
|
1876
|
+
* The 默认模型 value for a chain: the official V4 id when the chain TAIL
|
|
1877
|
+
* is that model (Flash XOR Pro — leading 默认降级链 entries allowed);
|
|
1878
|
+
* `''` for an empty chain or a chain whose last entry is not official
|
|
1879
|
+
* (the panel reads back unselected and save validation blocks the value).
|
|
1880
|
+
*/
|
|
1881
|
+
function allDayModelOf(chain) {
|
|
1882
|
+
const tail = chain.length >= 1 ? chain[chain.length - 1] : void 0;
|
|
1883
|
+
return tail === ALL_DAY_FLASH || tail === ALL_DAY_PRO ? tail : "";
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* The 默认降级链 editor row: the leading entries BEFORE the official-V4
|
|
1887
|
+
* tail, or the whole chain while the tail is not official (the draft
|
|
1888
|
+
* rides the accepted value until a 默认模型 pick).
|
|
1889
|
+
*/
|
|
1890
|
+
function allDayChainRowOf(chain, catalog) {
|
|
1891
|
+
return rootChainToRows(allDayModelOf(chain) === "" ? chain : chain.slice(0, -1), catalog)[0];
|
|
1892
|
+
}
|
|
1231
1893
|
/** Split scalars from the row editors (rootChain / role entities / role rules). */
|
|
1232
1894
|
function scalarsOf(config) {
|
|
1233
1895
|
return {
|
|
@@ -1237,7 +1899,8 @@ window.__ModuleLoader__.load({
|
|
|
1237
1899
|
revertPolicy: config.revertPolicy,
|
|
1238
1900
|
maxSwitchesPerStep: config.maxSwitchesPerStep,
|
|
1239
1901
|
alwaysModeRetryCap: config.alwaysModeRetryCap,
|
|
1240
|
-
roleAutoMatch: config.roleAutoMatch
|
|
1902
|
+
roleAutoMatch: config.roleAutoMatch,
|
|
1903
|
+
tz: config.tz ?? "Asia/Shanghai"
|
|
1241
1904
|
};
|
|
1242
1905
|
}
|
|
1243
1906
|
/**
|
|
@@ -1255,13 +1918,22 @@ window.__ModuleLoader__.load({
|
|
|
1255
1918
|
* `true` even for a legacy config that never declared the key — so the
|
|
1256
1919
|
* toggle always renders (default on) and a save persists the resolved value
|
|
1257
1920
|
* (AC-7 re-scope, PM decision 2026-08-17 Option A).
|
|
1921
|
+
*
|
|
1922
|
+
* All-day: rootChain is composed from the 默认降级链 editor's leading
|
|
1923
|
+
* selectors plus the 默认模型 tail (exactly one official V4 — Flash XOR
|
|
1924
|
+
* Pro). While no tail is selected the ACCEPTED chain rides through
|
|
1925
|
+
* untouched. `timeSlots` is rebuilt from the slot rows every render. `tz`
|
|
1926
|
+
* is a card scalar: preset rows lock it to Asia/Shanghai; custom rows
|
|
1927
|
+
* follow the selected timezone.
|
|
1258
1928
|
*/
|
|
1259
|
-
function assembleConfig(scalars,
|
|
1929
|
+
function assembleConfig(scalars, allDayModel, acceptedRootChain, allDayChainRow, roleRows, ruleRows, originalRoles, presets, roleAutoMatch, timeSlotRows) {
|
|
1260
1930
|
const list = mergeRoleExtras(roleRows, originalRoles);
|
|
1931
|
+
const trailingChain = rowsToRootChain([allDayChainRow]);
|
|
1932
|
+
const tz = resolvedSlotTz(timeSlotRows, scalars.tz);
|
|
1261
1933
|
return {
|
|
1262
1934
|
enabled: scalars.enabled,
|
|
1263
1935
|
triggerCodes: [...scalars.triggerCodes],
|
|
1264
|
-
rootChain:
|
|
1936
|
+
rootChain: allDayModel === "" ? [...acceptedRootChain] : [...trailingChain, allDayModel],
|
|
1265
1937
|
roles: {
|
|
1266
1938
|
list,
|
|
1267
1939
|
rules: rowsToRules(ruleRows)
|
|
@@ -1271,7 +1943,17 @@ window.__ModuleLoader__.load({
|
|
|
1271
1943
|
maxSwitchesPerStep: scalars.maxSwitchesPerStep,
|
|
1272
1944
|
alwaysModeRetryCap: scalars.alwaysModeRetryCap,
|
|
1273
1945
|
...presets === void 0 ? {} : { presets },
|
|
1274
|
-
roleAutoMatch
|
|
1946
|
+
roleAutoMatch,
|
|
1947
|
+
timeSlots: rowsToTimeSlots(timeSlotRows),
|
|
1948
|
+
tz
|
|
1949
|
+
};
|
|
1950
|
+
}
|
|
1951
|
+
/** An empty per-section validation-error record (the clean-draft shape). */
|
|
1952
|
+
function emptyValidationErrors() {
|
|
1953
|
+
return {
|
|
1954
|
+
main: [],
|
|
1955
|
+
sub: [],
|
|
1956
|
+
advanced: []
|
|
1275
1957
|
};
|
|
1276
1958
|
}
|
|
1277
1959
|
/**
|
|
@@ -1279,9 +1961,14 @@ window.__ModuleLoader__.load({
|
|
|
1279
1961
|
* role id format/reserved word/duplicates, undeclared rule role references
|
|
1280
1962
|
* (only reachable through the synthetic outside option — the dropdown
|
|
1281
1963
|
* itself constrains normal edits), and illegal selector entries in
|
|
1282
|
-
* rootChain and role chains. Returns one localized message per violation
|
|
1283
|
-
*
|
|
1284
|
-
*
|
|
1964
|
+
* rootChain and role chains. Returns one localized message per violation,
|
|
1965
|
+
* bucketed by the section that owns the offending field (PR #62 UX round
|
|
1966
|
+
* 2 — 主代理: allDay / timeSlots / slot* / tz / default model / default
|
|
1967
|
+
* chain; 子代理: role* / rule*; 高级选项: trigger / cooldown / revert /
|
|
1968
|
+
* always / roleAutoMatch — the scalars are never validated, so the
|
|
1969
|
+
* advanced bucket stays empty today). A non-empty result blocks
|
|
1970
|
+
* {@link save} — the draft is never written. `persona` is free text and
|
|
1971
|
+
* never validated.
|
|
1285
1972
|
*
|
|
1286
1973
|
* `seededIds` is the live trimmed-id → overridden map derived from
|
|
1287
1974
|
* `state.seeds` (spec §9.4): the empty-chain block relaxes for seeded ids
|
|
@@ -1290,33 +1977,57 @@ window.__ModuleLoader__.load({
|
|
|
1290
1977
|
* behavior is byte-identical.
|
|
1291
1978
|
*/
|
|
1292
1979
|
function validateDraft(draft, t, seededIds) {
|
|
1293
|
-
const errors =
|
|
1980
|
+
const errors = emptyValidationErrors();
|
|
1294
1981
|
const declaredIds = /* @__PURE__ */ new Set();
|
|
1295
1982
|
for (const role of draft.roles.list) {
|
|
1296
|
-
if (!ROLE_ID_PATTERN.test(role.id)) errors.push(t("validation.roleIdFormat", { id: role.id }));
|
|
1297
|
-
if (role.id === "inherit") errors.push(t("validation.roleIdReserved"));
|
|
1298
|
-
if (declaredIds.has(role.id)) errors.push(t("validation.roleIdDuplicate", { id: role.id }));
|
|
1983
|
+
if (!ROLE_ID_PATTERN.test(role.id)) errors.sub.push(t("validation.roleIdFormat", { id: role.id }));
|
|
1984
|
+
if (role.id === "inherit") errors.sub.push(t("validation.roleIdReserved"));
|
|
1985
|
+
if (declaredIds.has(role.id)) errors.sub.push(t("validation.roleIdDuplicate", { id: role.id }));
|
|
1299
1986
|
declaredIds.add(role.id);
|
|
1300
1987
|
for (const entry of role.chain ?? []) try {
|
|
1301
1988
|
parseSelector(entry);
|
|
1302
1989
|
} catch (error) {
|
|
1303
|
-
errors.push(t("validation.selector", {
|
|
1990
|
+
errors.sub.push(t("validation.selector", {
|
|
1304
1991
|
entry,
|
|
1305
1992
|
message: error.message
|
|
1306
1993
|
}));
|
|
1307
1994
|
}
|
|
1308
|
-
if ((role.chain ?? []).length === 0 && !seededIds.has(role.id.trim())) errors.push(t("validation.roleChainRequired", { id: role.id }));
|
|
1995
|
+
if ((role.chain ?? []).length === 0 && !seededIds.has(role.id.trim())) errors.sub.push(t("validation.roleChainRequired", { id: role.id }));
|
|
1309
1996
|
}
|
|
1997
|
+
const allDayTail = draft.rootChain.length >= 1 ? draft.rootChain[draft.rootChain.length - 1] : void 0;
|
|
1998
|
+
if (allDayTail !== ALL_DAY_FLASH && allDayTail !== ALL_DAY_PRO) errors.main.push(t("validation.allDayRequired"));
|
|
1310
1999
|
for (const entry of draft.rootChain) try {
|
|
1311
2000
|
parseSelector(entry);
|
|
1312
2001
|
} catch (error) {
|
|
1313
|
-
errors.push(t("validation.selector", {
|
|
2002
|
+
errors.main.push(t("validation.selector", {
|
|
1314
2003
|
entry,
|
|
1315
2004
|
message: error.message
|
|
1316
2005
|
}));
|
|
1317
2006
|
}
|
|
2007
|
+
const seenSlotPresets = /* @__PURE__ */ new Set();
|
|
2008
|
+
for (const row of draft.timeSlots ?? []) {
|
|
2009
|
+
if (row.kind !== "preset" && row.kind !== "custom") errors.main.push(t("validation.slotKind"));
|
|
2010
|
+
if (row.kind === "preset") {
|
|
2011
|
+
if (typeof row.preset !== "string" || !SLOT_PRESET_IDS.includes(row.preset)) errors.main.push(t("validation.slotPresetUnknown", { preset: row.preset }));
|
|
2012
|
+
else if (seenSlotPresets.has(row.preset)) errors.main.push(t("validation.slotPresetDuplicate", { preset: row.preset }));
|
|
2013
|
+
else seenSlotPresets.add(row.preset);
|
|
2014
|
+
if (row.start !== void 0 || row.end !== void 0 || row.days !== void 0 && row.days.length > 0) errors.main.push(t("validation.slotPresetFrozen"));
|
|
2015
|
+
} else if (row.kind === "custom") {
|
|
2016
|
+
if (typeof row.start !== "string" || typeof row.end !== "string" || !HHMM_RE.test(row.start) || !HHMM_RE.test(row.end)) errors.main.push(t("validation.slotWindow"));
|
|
2017
|
+
if (row.days !== void 0 && row.days.some((day) => !Number.isInteger(day) || day < 0 || day > 6)) errors.main.push(t("validation.slotDays"));
|
|
2018
|
+
}
|
|
2019
|
+
for (const entry of row.chain) try {
|
|
2020
|
+
parseSelector(entry);
|
|
2021
|
+
} catch (error) {
|
|
2022
|
+
errors.main.push(t("validation.selector", {
|
|
2023
|
+
entry,
|
|
2024
|
+
message: error.message
|
|
2025
|
+
}));
|
|
2026
|
+
}
|
|
2027
|
+
if (row.chain.length === 0) errors.main.push(t("validation.slotChainRequired"));
|
|
2028
|
+
}
|
|
1318
2029
|
const validTargets = /* @__PURE__ */ new Set([...declaredIds, INHERIT_ROLE_ID]);
|
|
1319
|
-
for (const rule of draft.roles.rules) if (!validTargets.has(rule.role)) errors.push(t("validation.ruleRoleUndeclared", { role: rule.role }));
|
|
2030
|
+
for (const rule of draft.roles.rules) if (!validTargets.has(rule.role)) errors.sub.push(t("validation.ruleRoleUndeclared", { role: rule.role }));
|
|
1320
2031
|
return errors;
|
|
1321
2032
|
}
|
|
1322
2033
|
/**
|
|
@@ -1345,6 +2056,20 @@ window.__ModuleLoader__.load({
|
|
|
1345
2056
|
const parsed = Number.parseInt(raw, 10);
|
|
1346
2057
|
return Number.isNaN(parsed) ? 0 : Math.max(0, parsed);
|
|
1347
2058
|
}
|
|
2059
|
+
/**
|
|
2060
|
+
* Custom time-slot rows whose window is not valid `HH:mm` — drives the
|
|
2061
|
+
* inline red border after a blocked save attempt (same derivation pattern
|
|
2062
|
+
* as {@link collectInvalidRoleIds}: one pass per render, index lookup per
|
|
2063
|
+
* row).
|
|
2064
|
+
*/
|
|
2065
|
+
function collectInvalidSlotRows(rows) {
|
|
2066
|
+
const invalid = /* @__PURE__ */ new Set();
|
|
2067
|
+
rows.forEach((row, index) => {
|
|
2068
|
+
if (row.kind === "preset") return;
|
|
2069
|
+
if (!HHMM_RE.test(row.start) || !HHMM_RE.test(row.end)) invalid.add(index);
|
|
2070
|
+
});
|
|
2071
|
+
return invalid;
|
|
2072
|
+
}
|
|
1348
2073
|
/** The catalog faces the dropdowns classify against; undefined while unready. */
|
|
1349
2074
|
function catalogOf(state) {
|
|
1350
2075
|
return state.catalogStatus === "ready" ? {
|
|
@@ -1533,24 +2258,79 @@ window.__ModuleLoader__.load({
|
|
|
1533
2258
|
if (snapshot.switchesStatus === "idle") controller.loadSwitches();
|
|
1534
2259
|
}, [controller]);
|
|
1535
2260
|
const [scalars, setScalars] = (0, react.useState)(() => scalarsOf(defaultFallbacksConfig));
|
|
1536
|
-
const [
|
|
2261
|
+
const [allDayModel, setAllDayModel] = (0, react.useState)(() => allDayModelOf(defaultFallbacksConfig.rootChain));
|
|
2262
|
+
const [allDayChainRow, setAllDayChainRow] = (0, react.useState)(() => allDayChainRowOf(defaultFallbacksConfig.rootChain, void 0));
|
|
2263
|
+
const [timeSlotRows, setTimeSlotRows] = (0, react.useState)(() => timeSlotsToRows(defaultFallbacksConfig.timeSlots ?? []));
|
|
1537
2264
|
const [roleRows, setRoleRows] = (0, react.useState)(() => rolesToRows(defaultFallbacksConfig.roles.list));
|
|
1538
2265
|
const [ruleRows, setRuleRows] = (0, react.useState)(() => rulesToRows(defaultFallbacksConfig.roles.rules));
|
|
1539
|
-
const [
|
|
2266
|
+
const [presetToAdd, setPresetToAdd] = (0, react.useState)("");
|
|
2267
|
+
const [validationErrors, setValidationErrors] = (0, react.useState)(emptyValidationErrors);
|
|
1540
2268
|
const [validationAttempted, setValidationAttempted] = (0, react.useState)(false);
|
|
2269
|
+
const [lastSaveSection, setLastSaveSection] = (0, react.useState)(null);
|
|
1541
2270
|
const seededConfigKey = (0, react.useRef)(null);
|
|
2271
|
+
const draft = assembleConfig(scalars, allDayModel, state.config.rootChain, allDayChainRow, roleRows, ruleRows, state.config.roles.list, state.config.presets, scalars.roleAutoMatch, timeSlotRows);
|
|
2272
|
+
const hasEmptyRuleRows = ruleRows.some((row) => row.role === "");
|
|
2273
|
+
const enabledDirty = scalars.enabled !== state.config.enabled;
|
|
2274
|
+
const mainDirty = enabledDirty || JSON.stringify([...draft.rootChain, draft.timeSlots]) !== JSON.stringify([...state.config.rootChain, state.config.timeSlots ?? []]);
|
|
2275
|
+
const subDirty = hasEmptyRuleRows || JSON.stringify(draft.roles) !== JSON.stringify(state.config.roles);
|
|
2276
|
+
const advancedDirty = JSON.stringify([
|
|
2277
|
+
draft.triggerCodes,
|
|
2278
|
+
draft.cooldownMs,
|
|
2279
|
+
draft.revertPolicy,
|
|
2280
|
+
draft.maxSwitchesPerStep,
|
|
2281
|
+
draft.alwaysModeRetryCap,
|
|
2282
|
+
draft.roleAutoMatch
|
|
2283
|
+
]) !== JSON.stringify([
|
|
2284
|
+
state.config.triggerCodes,
|
|
2285
|
+
state.config.cooldownMs,
|
|
2286
|
+
state.config.revertPolicy,
|
|
2287
|
+
state.config.maxSwitchesPerStep,
|
|
2288
|
+
state.config.alwaysModeRetryCap,
|
|
2289
|
+
state.config.roleAutoMatch
|
|
2290
|
+
]);
|
|
2291
|
+
const dirty = mainDirty || subDirty || advancedDirty;
|
|
2292
|
+
const firstSeedDone = (0, react.useRef)(false);
|
|
2293
|
+
const forceReseed = (0, react.useRef)(false);
|
|
1542
2294
|
(0, react.useEffect)(() => {
|
|
1543
2295
|
if (state.status !== "ready") return;
|
|
1544
2296
|
const key = JSON.stringify(state.config);
|
|
1545
2297
|
if (seededConfigKey.current === key) return;
|
|
1546
2298
|
seededConfigKey.current = key;
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
2299
|
+
const firstSeed = !firstSeedDone.current;
|
|
2300
|
+
firstSeedDone.current = true;
|
|
2301
|
+
const force = forceReseed.current;
|
|
2302
|
+
forceReseed.current = false;
|
|
2303
|
+
const catalog = catalogOf(state);
|
|
2304
|
+
if (firstSeed || force || !mainDirty) {
|
|
2305
|
+
setAllDayModel(allDayModelOf(state.config.rootChain));
|
|
2306
|
+
setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalog));
|
|
2307
|
+
setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalog));
|
|
2308
|
+
setScalars((prev) => ({
|
|
2309
|
+
...prev,
|
|
2310
|
+
enabled: state.config.enabled,
|
|
2311
|
+
tz: state.config.tz ?? "Asia/Shanghai"
|
|
2312
|
+
}));
|
|
2313
|
+
}
|
|
2314
|
+
if (firstSeed || force || !subDirty) {
|
|
2315
|
+
setRoleRows(rolesToRows(state.config.roles.list, catalog));
|
|
2316
|
+
setRuleRows(rulesToRows(state.config.roles.rules, catalog));
|
|
2317
|
+
}
|
|
2318
|
+
if (firstSeed || force || !advancedDirty) setScalars((prev) => ({
|
|
2319
|
+
...prev,
|
|
2320
|
+
triggerCodes: [...state.config.triggerCodes],
|
|
2321
|
+
cooldownMs: state.config.cooldownMs,
|
|
2322
|
+
revertPolicy: state.config.revertPolicy,
|
|
2323
|
+
maxSwitchesPerStep: state.config.maxSwitchesPerStep,
|
|
2324
|
+
alwaysModeRetryCap: state.config.alwaysModeRetryCap,
|
|
2325
|
+
roleAutoMatch: state.config.roleAutoMatch
|
|
2326
|
+
}));
|
|
2327
|
+
}, [
|
|
2328
|
+
state.status,
|
|
2329
|
+
state.config,
|
|
2330
|
+
mainDirty,
|
|
2331
|
+
subDirty,
|
|
2332
|
+
advancedDirty
|
|
2333
|
+
]);
|
|
1554
2334
|
const updateScalars = (mutator) => {
|
|
1555
2335
|
setScalars((prev) => {
|
|
1556
2336
|
const next = {
|
|
@@ -1561,17 +2341,32 @@ window.__ModuleLoader__.load({
|
|
|
1561
2341
|
return next;
|
|
1562
2342
|
});
|
|
1563
2343
|
};
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1566
|
-
...row
|
|
1567
|
-
|
|
1568
|
-
...
|
|
2344
|
+
const updateTimeSlotRow = (index, patch) => {
|
|
2345
|
+
setTimeSlotRows((rows) => {
|
|
2346
|
+
const next = rows.map((row) => ({ ...row }));
|
|
2347
|
+
next[index] = {
|
|
2348
|
+
...next[index],
|
|
1569
2349
|
...patch
|
|
1570
|
-
}
|
|
1571
|
-
|
|
2350
|
+
};
|
|
2351
|
+
return next;
|
|
2352
|
+
});
|
|
2353
|
+
};
|
|
2354
|
+
const updateTimeSlotSelector = (rowIndex, selectorIndex, patch) => {
|
|
2355
|
+
setTimeSlotRows((rows) => {
|
|
2356
|
+
const next = rows.map((row) => ({
|
|
2357
|
+
...row,
|
|
2358
|
+
selectors: row.selectors.map((selector) => ({ ...selector }))
|
|
2359
|
+
}));
|
|
2360
|
+
const selectors = next[rowIndex].selectors;
|
|
2361
|
+
selectors[selectorIndex] = {
|
|
2362
|
+
...selectors[selectorIndex],
|
|
2363
|
+
...patch
|
|
2364
|
+
};
|
|
2365
|
+
return next;
|
|
2366
|
+
});
|
|
1572
2367
|
};
|
|
1573
|
-
const
|
|
1574
|
-
|
|
2368
|
+
const addTimeSlotSelector = (rowIndex) => {
|
|
2369
|
+
setTimeSlotRows((rows) => rows.map((row, index) => index === rowIndex ? {
|
|
1575
2370
|
...row,
|
|
1576
2371
|
selectors: [...row.selectors, {
|
|
1577
2372
|
wildcard: false,
|
|
@@ -1580,12 +2375,88 @@ window.__ModuleLoader__.load({
|
|
|
1580
2375
|
}]
|
|
1581
2376
|
} : row));
|
|
1582
2377
|
};
|
|
1583
|
-
const
|
|
1584
|
-
|
|
2378
|
+
const removeTimeSlotSelector = (rowIndex, selectorIndex) => {
|
|
2379
|
+
setTimeSlotRows((rows) => rows.map((row, index) => index === rowIndex ? {
|
|
1585
2380
|
...row,
|
|
1586
2381
|
selectors: row.selectors.filter((_, sIndex) => sIndex !== selectorIndex)
|
|
1587
2382
|
} : row));
|
|
1588
2383
|
};
|
|
2384
|
+
const addPresetSlotRow = () => {
|
|
2385
|
+
if (presetToAdd === "") return;
|
|
2386
|
+
if ((presetToAdd === "glm-peak" || presetToAdd === "glm-valley") && !glmConfigured) return;
|
|
2387
|
+
setTimeSlotRows((rows) => [...rows, {
|
|
2388
|
+
kind: "preset",
|
|
2389
|
+
preset: presetToAdd,
|
|
2390
|
+
start: "",
|
|
2391
|
+
end: "",
|
|
2392
|
+
days: [],
|
|
2393
|
+
name: "",
|
|
2394
|
+
collapsed: false,
|
|
2395
|
+
selectors: []
|
|
2396
|
+
}]);
|
|
2397
|
+
setPresetToAdd("");
|
|
2398
|
+
};
|
|
2399
|
+
const addCustomSlotRow = () => {
|
|
2400
|
+
setTimeSlotRows((rows) => [...rows, {
|
|
2401
|
+
kind: "custom",
|
|
2402
|
+
start: "",
|
|
2403
|
+
end: "",
|
|
2404
|
+
days: [],
|
|
2405
|
+
name: "",
|
|
2406
|
+
collapsed: false,
|
|
2407
|
+
selectors: []
|
|
2408
|
+
}]);
|
|
2409
|
+
};
|
|
2410
|
+
const removeTimeSlotRow = (index) => {
|
|
2411
|
+
setTimeSlotRows((rows) => rows.filter((_, rowIndex) => rowIndex !== index));
|
|
2412
|
+
};
|
|
2413
|
+
const moveTimeSlotRow = (index, delta) => {
|
|
2414
|
+
setTimeSlotRows((rows) => {
|
|
2415
|
+
const target = index + delta;
|
|
2416
|
+
if (target < 0 || target >= rows.length) return rows;
|
|
2417
|
+
const next = rows.map((row) => ({ ...row }));
|
|
2418
|
+
const moved = next[index];
|
|
2419
|
+
next[index] = next[target];
|
|
2420
|
+
next[target] = moved;
|
|
2421
|
+
return next;
|
|
2422
|
+
});
|
|
2423
|
+
};
|
|
2424
|
+
const [draggedSlotIndex, setDraggedSlotIndex] = (0, react.useState)(null);
|
|
2425
|
+
const [overSlotIndex, setOverSlotIndex] = (0, react.useState)(null);
|
|
2426
|
+
const reorderTimeSlotRow = (from, to) => {
|
|
2427
|
+
setTimeSlotRows((rows) => {
|
|
2428
|
+
if (from === to || from < 0 || to < 0 || from >= rows.length || to >= rows.length) return rows;
|
|
2429
|
+
const next = rows.map((row) => ({ ...row }));
|
|
2430
|
+
const [moved] = next.splice(from, 1);
|
|
2431
|
+
next.splice(to, 0, moved);
|
|
2432
|
+
return next;
|
|
2433
|
+
});
|
|
2434
|
+
};
|
|
2435
|
+
const updateAllDayChainSelector = (selectorIndex, patch) => {
|
|
2436
|
+
setAllDayChainRow((row) => ({
|
|
2437
|
+
...row,
|
|
2438
|
+
selectors: row.selectors.map((selector, index) => index === selectorIndex ? {
|
|
2439
|
+
...selector,
|
|
2440
|
+
...patch
|
|
2441
|
+
} : selector)
|
|
2442
|
+
}));
|
|
2443
|
+
};
|
|
2444
|
+
const addAllDayChainSelector = () => {
|
|
2445
|
+
setAllDayChainRow((row) => ({
|
|
2446
|
+
...row,
|
|
2447
|
+
selectors: [...row.selectors, {
|
|
2448
|
+
wildcard: false,
|
|
2449
|
+
provider: null,
|
|
2450
|
+
model: null
|
|
2451
|
+
}]
|
|
2452
|
+
}));
|
|
2453
|
+
};
|
|
2454
|
+
const removeAllDayChainSelector = (selectorIndex) => {
|
|
2455
|
+
setAllDayChainRow((row) => ({
|
|
2456
|
+
...row,
|
|
2457
|
+
selectors: row.selectors.filter((_, index) => index !== selectorIndex)
|
|
2458
|
+
}));
|
|
2459
|
+
};
|
|
1589
2460
|
const updateRoleRow = (index, patch) => {
|
|
1590
2461
|
setRoleRows((rows) => {
|
|
1591
2462
|
const next = rows.map((row) => ({ ...row }));
|
|
@@ -1631,7 +2502,8 @@ window.__ModuleLoader__.load({
|
|
|
1631
2502
|
id: "",
|
|
1632
2503
|
persona: "",
|
|
1633
2504
|
selectors: [],
|
|
1634
|
-
fallback: "inherit-root"
|
|
2505
|
+
fallback: "inherit-root",
|
|
2506
|
+
collapsed: true
|
|
1635
2507
|
}]);
|
|
1636
2508
|
};
|
|
1637
2509
|
const removeRole = (index) => {
|
|
@@ -1647,15 +2519,21 @@ window.__ModuleLoader__.load({
|
|
|
1647
2519
|
return next;
|
|
1648
2520
|
});
|
|
1649
2521
|
};
|
|
1650
|
-
const
|
|
1651
|
-
|
|
1652
|
-
|
|
2522
|
+
const allValidationErrors = [
|
|
2523
|
+
...validationErrors.main,
|
|
2524
|
+
...validationErrors.sub,
|
|
2525
|
+
...validationErrors.advanced
|
|
2526
|
+
];
|
|
1653
2527
|
const saving = state.status === "saving";
|
|
1654
2528
|
const writable = state.writable;
|
|
1655
2529
|
const unknownCodes = scalars.triggerCodes.filter((code) => !KNOWN_TRIGGER_CODES.includes(code));
|
|
1656
|
-
const
|
|
2530
|
+
const presetsPresent = timeSlotRows.some((row) => row.kind === "preset");
|
|
2531
|
+
const glmConfigured = state.configuredProviders.some((entry) => entry.provider === "zai-coding-cn");
|
|
2532
|
+
const slotState = resolveSlotState(state.config, /* @__PURE__ */ new Date(), scalars.tz);
|
|
2533
|
+
const activeSlotIndex = slotState.winner === "all-day" ? -1 : state.config.timeSlots?.indexOf(slotState.winner) ?? -1;
|
|
1657
2534
|
const roleOptions = ruleRoleOptions({ list: roleRows });
|
|
1658
2535
|
const invalidRoleIds = validationAttempted ? collectInvalidRoleIds(roleRows) : null;
|
|
2536
|
+
const invalidSlotRows = validationAttempted ? collectInvalidSlotRows(timeSlotRows) : null;
|
|
1659
2537
|
const seededIds = /* @__PURE__ */ new Map();
|
|
1660
2538
|
for (const seed of state.seeds) seededIds.set(seed.id.trim(), seed.overridden);
|
|
1661
2539
|
const latestSwitch = state.switches[0];
|
|
@@ -1674,45 +2552,129 @@ window.__ModuleLoader__.load({
|
|
|
1674
2552
|
};
|
|
1675
2553
|
switchesLine = latestSwitch.reason === "role-inject" ? t("status.switches.compact.roleInject", params) : t("status.switches.compact", params);
|
|
1676
2554
|
}
|
|
1677
|
-
const
|
|
2555
|
+
const catalogSeededSections = (0, react.useRef)({
|
|
2556
|
+
epoch: null,
|
|
2557
|
+
main: false,
|
|
2558
|
+
sub: false
|
|
2559
|
+
});
|
|
1678
2560
|
(0, react.useEffect)(() => {
|
|
1679
2561
|
if (state.catalogStatus !== "ready") return;
|
|
1680
|
-
|
|
1681
|
-
if (
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
2562
|
+
const seed = catalogSeededSections.current;
|
|
2563
|
+
if (seed.epoch !== state.catalogEpoch) {
|
|
2564
|
+
seed.epoch = state.catalogEpoch;
|
|
2565
|
+
seed.main = false;
|
|
2566
|
+
seed.sub = false;
|
|
2567
|
+
}
|
|
2568
|
+
const catalog = catalogOf(state);
|
|
2569
|
+
if (!mainDirty && !seed.main) {
|
|
2570
|
+
seed.main = true;
|
|
2571
|
+
setAllDayModel(allDayModelOf(state.config.rootChain));
|
|
2572
|
+
setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalog));
|
|
2573
|
+
setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalog));
|
|
2574
|
+
}
|
|
2575
|
+
if (!subDirty && !seed.sub) {
|
|
2576
|
+
seed.sub = true;
|
|
2577
|
+
setRoleRows(rolesToRows(state.config.roles.list, catalog));
|
|
2578
|
+
setRuleRows(rulesToRows(state.config.roles.rules, catalog));
|
|
2579
|
+
}
|
|
1686
2580
|
}, [
|
|
1687
2581
|
state.catalogStatus,
|
|
1688
2582
|
state.catalogEpoch,
|
|
1689
2583
|
state.config,
|
|
1690
|
-
|
|
2584
|
+
mainDirty,
|
|
2585
|
+
subDirty
|
|
1691
2586
|
]);
|
|
1692
|
-
const
|
|
2587
|
+
const sectionPatch = (section) => {
|
|
2588
|
+
const base = {
|
|
2589
|
+
...state.config,
|
|
2590
|
+
enabled: scalars.enabled
|
|
2591
|
+
};
|
|
2592
|
+
switch (section) {
|
|
2593
|
+
case "main": return {
|
|
2594
|
+
...base,
|
|
2595
|
+
rootChain: draft.rootChain,
|
|
2596
|
+
timeSlots: draft.timeSlots,
|
|
2597
|
+
tz: draft.tz
|
|
2598
|
+
};
|
|
2599
|
+
case "sub": return {
|
|
2600
|
+
...base,
|
|
2601
|
+
roles: draft.roles
|
|
2602
|
+
};
|
|
2603
|
+
case "advanced": return {
|
|
2604
|
+
...base,
|
|
2605
|
+
triggerCodes: draft.triggerCodes,
|
|
2606
|
+
cooldownMs: draft.cooldownMs,
|
|
2607
|
+
revertPolicy: draft.revertPolicy,
|
|
2608
|
+
maxSwitchesPerStep: draft.maxSwitchesPerStep,
|
|
2609
|
+
alwaysModeRetryCap: draft.alwaysModeRetryCap,
|
|
2610
|
+
roleAutoMatch: draft.roleAutoMatch
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
};
|
|
2614
|
+
const save = (section) => {
|
|
2615
|
+
setLastSaveSection(section);
|
|
1693
2616
|
const errors = validateDraft(draft, t, seededIds);
|
|
1694
|
-
if (hasEmptyRuleRows) errors.push(t("validation.ruleRoleRequired"));
|
|
1695
|
-
if (errors.length > 0) {
|
|
2617
|
+
if (section === "sub" && hasEmptyRuleRows) errors.sub.push(t("validation.ruleRoleRequired"));
|
|
2618
|
+
if (errors[section].length > 0) {
|
|
1696
2619
|
setValidationErrors(errors);
|
|
1697
2620
|
setValidationAttempted(true);
|
|
1698
2621
|
return;
|
|
1699
2622
|
}
|
|
1700
|
-
setValidationErrors(
|
|
2623
|
+
setValidationErrors(emptyValidationErrors());
|
|
2624
|
+
setValidationAttempted(false);
|
|
2625
|
+
controller.save(sectionPatch(section));
|
|
2626
|
+
};
|
|
2627
|
+
const saveEnabled = () => {
|
|
2628
|
+
setLastSaveSection("main");
|
|
2629
|
+
setValidationErrors(emptyValidationErrors());
|
|
2630
|
+
setValidationAttempted(false);
|
|
2631
|
+
controller.save({
|
|
2632
|
+
...state.config,
|
|
2633
|
+
enabled: scalars.enabled
|
|
2634
|
+
});
|
|
2635
|
+
};
|
|
2636
|
+
const discardSection = (section) => {
|
|
2637
|
+
switch (section) {
|
|
2638
|
+
case "main":
|
|
2639
|
+
setAllDayModel(allDayModelOf(state.config.rootChain));
|
|
2640
|
+
setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalogOf(state)));
|
|
2641
|
+
setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalogOf(state)));
|
|
2642
|
+
setScalars((prev) => ({
|
|
2643
|
+
...prev,
|
|
2644
|
+
enabled: state.config.enabled,
|
|
2645
|
+
tz: state.config.tz ?? "Asia/Shanghai"
|
|
2646
|
+
}));
|
|
2647
|
+
break;
|
|
2648
|
+
case "sub":
|
|
2649
|
+
setRoleRows(rolesToRows(state.config.roles.list, catalogOf(state)));
|
|
2650
|
+
setRuleRows(rulesToRows(state.config.roles.rules, catalogOf(state)));
|
|
2651
|
+
break;
|
|
2652
|
+
case "advanced": setScalars((prev) => ({
|
|
2653
|
+
...prev,
|
|
2654
|
+
triggerCodes: [...state.config.triggerCodes],
|
|
2655
|
+
cooldownMs: state.config.cooldownMs,
|
|
2656
|
+
revertPolicy: state.config.revertPolicy,
|
|
2657
|
+
maxSwitchesPerStep: state.config.maxSwitchesPerStep,
|
|
2658
|
+
alwaysModeRetryCap: state.config.alwaysModeRetryCap,
|
|
2659
|
+
roleAutoMatch: state.config.roleAutoMatch
|
|
2660
|
+
}));
|
|
2661
|
+
}
|
|
2662
|
+
setValidationErrors(emptyValidationErrors());
|
|
1701
2663
|
setValidationAttempted(false);
|
|
1702
|
-
controller.save(draft);
|
|
1703
2664
|
};
|
|
1704
|
-
const
|
|
1705
|
-
setScalars(
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
setValidationErrors(
|
|
2665
|
+
const discardEnabled = () => {
|
|
2666
|
+
setScalars((prev) => ({
|
|
2667
|
+
...prev,
|
|
2668
|
+
enabled: state.config.enabled
|
|
2669
|
+
}));
|
|
2670
|
+
setValidationErrors(emptyValidationErrors());
|
|
1710
2671
|
setValidationAttempted(false);
|
|
1711
2672
|
};
|
|
1712
2673
|
(0, react.useEffect)(() => {
|
|
1713
2674
|
if (!validationAttempted) return;
|
|
1714
|
-
|
|
1715
|
-
|
|
2675
|
+
const errors = validateDraft(draft, t, seededIds);
|
|
2676
|
+
if (errors.main.length === 0 && errors.sub.length === 0 && errors.advanced.length === 0 && !ruleRows.some((row) => row.role === "")) {
|
|
2677
|
+
setValidationErrors(emptyValidationErrors());
|
|
1716
2678
|
setValidationAttempted(false);
|
|
1717
2679
|
}
|
|
1718
2680
|
}, [
|
|
@@ -1721,13 +2683,10 @@ window.__ModuleLoader__.load({
|
|
|
1721
2683
|
ruleRows,
|
|
1722
2684
|
t
|
|
1723
2685
|
]);
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
setConfirmingReset(false);
|
|
1729
|
-
});
|
|
1730
|
-
};
|
|
2686
|
+
(0, react.useEffect)(() => {
|
|
2687
|
+
if (state.status === "ready") setLastSaveSection(null);
|
|
2688
|
+
if (state.status === "error") forceReseed.current = false;
|
|
2689
|
+
}, [state.status]);
|
|
1731
2690
|
const [userOpen, setUserOpen] = (0, react.useState)(false);
|
|
1732
2691
|
const [advancedOpen, setAdvancedOpen] = (0, react.useState)(false);
|
|
1733
2692
|
const degradedLatch = (0, react.useRef)(false);
|
|
@@ -1768,871 +2727,1323 @@ window.__ModuleLoader__.load({
|
|
|
1768
2727
|
});
|
|
1769
2728
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
1770
2729
|
className: open ? `${FallbacksCard_module_css_default.card} ${FallbacksCard_module_css_default.cardOpen}` : FallbacksCard_module_css_default.card,
|
|
1771
|
-
children: [
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
className: FallbacksCard_module_css_default.noticeRow,
|
|
1783
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1784
|
-
className: FallbacksCard_module_css_default.error,
|
|
1785
|
-
role: "alert",
|
|
1786
|
-
children: t("error.generic", { message: state.error })
|
|
1787
|
-
}), !state.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1788
|
-
variant: "outline",
|
|
1789
|
-
size: "sm",
|
|
1790
|
-
onClick: () => {
|
|
1791
|
-
controller.load();
|
|
1792
|
-
},
|
|
1793
|
-
children: t("retry")
|
|
1794
|
-
})]
|
|
1795
|
-
}),
|
|
1796
|
-
validationErrors.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2730
|
+
children: [header, open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2731
|
+
className: FallbacksCard_module_css_default.body,
|
|
2732
|
+
children: [
|
|
2733
|
+
state.legacyKeys.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2734
|
+
className: FallbacksCard_module_css_default.legacyNotice,
|
|
2735
|
+
role: "status",
|
|
2736
|
+
children: t("legacy.banner", { keys: state.legacyKeys.join(", ") })
|
|
2737
|
+
}),
|
|
2738
|
+
state.status === "error" && state.error !== null && lastSaveSection === null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2739
|
+
className: FallbacksCard_module_css_default.noticeRow,
|
|
2740
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1797
2741
|
className: FallbacksCard_module_css_default.error,
|
|
1798
2742
|
role: "alert",
|
|
1799
|
-
children:
|
|
1800
|
-
}),
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
2743
|
+
children: t("error.generic", { message: state.error })
|
|
2744
|
+
}), !state.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2745
|
+
variant: "outline",
|
|
2746
|
+
size: "sm",
|
|
2747
|
+
onClick: () => {
|
|
2748
|
+
controller.load();
|
|
2749
|
+
},
|
|
2750
|
+
children: t("retry")
|
|
2751
|
+
})]
|
|
2752
|
+
}),
|
|
2753
|
+
degraded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2754
|
+
className: FallbacksCard_module_css_default.notice,
|
|
2755
|
+
role: "status",
|
|
2756
|
+
children: t("unavailable")
|
|
2757
|
+
}),
|
|
2758
|
+
state.status === "ready" && !state.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2759
|
+
className: FallbacksCard_module_css_default.readOnly,
|
|
2760
|
+
role: "status",
|
|
2761
|
+
children: t("readOnly")
|
|
2762
|
+
}),
|
|
2763
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2764
|
+
className: FallbacksCard_module_css_default.form,
|
|
2765
|
+
children: [
|
|
2766
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2767
|
+
className: FallbacksCard_module_css_default.checkboxRow,
|
|
2768
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2769
|
+
className: FallbacksCard_module_css_default.checkLabel,
|
|
2770
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2771
|
+
className: FallbacksCard_module_css_default.checkLabelTitle,
|
|
2772
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
2773
|
+
htmlFor: "fallbacks-enabled",
|
|
2774
|
+
children: t("enabled.label")
|
|
2775
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2776
|
+
label: t("enabled.tooltip"),
|
|
2777
|
+
disabled: !writable
|
|
1830
2778
|
})]
|
|
1831
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
className: FallbacksCard_module_css_default.checkbox,
|
|
1835
|
-
checked: scalars.enabled,
|
|
1836
|
-
disabled: !writable,
|
|
1837
|
-
onChange: (event) => {
|
|
1838
|
-
updateScalars((draft) => {
|
|
1839
|
-
draft.enabled = event.target.checked;
|
|
1840
|
-
});
|
|
1841
|
-
}
|
|
2779
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2780
|
+
className: FallbacksCard_module_css_default.checkLabelDesc,
|
|
2781
|
+
children: t("enabled.hint")
|
|
1842
2782
|
})]
|
|
1843
|
-
}),
|
|
1844
|
-
|
|
2783
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2784
|
+
id: "fallbacks-enabled",
|
|
2785
|
+
type: "checkbox",
|
|
2786
|
+
className: FallbacksCard_module_css_default.checkbox,
|
|
2787
|
+
checked: scalars.enabled,
|
|
2788
|
+
disabled: !writable,
|
|
2789
|
+
onChange: (event) => {
|
|
2790
|
+
updateScalars((draft) => {
|
|
2791
|
+
draft.enabled = event.target.checked;
|
|
2792
|
+
});
|
|
2793
|
+
}
|
|
2794
|
+
})]
|
|
2795
|
+
}),
|
|
2796
|
+
!scalars.enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2797
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1845
2798
|
className: FallbacksCard_module_css_default.offNotice,
|
|
1846
2799
|
children: t("enabled.off")
|
|
1847
2800
|
}),
|
|
1848
|
-
|
|
1849
|
-
className: FallbacksCard_module_css_default.
|
|
1850
|
-
|
|
1851
|
-
children:
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1924
|
-
|
|
1925
|
-
children:
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2801
|
+
allValidationErrors.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2802
|
+
className: FallbacksCard_module_css_default.error,
|
|
2803
|
+
role: "alert",
|
|
2804
|
+
children: `${t("validation.blocked")}${allValidationErrors.join("; ")}`
|
|
2805
|
+
}),
|
|
2806
|
+
lastSaveSection === "main" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2807
|
+
className: FallbacksCard_module_css_default.error,
|
|
2808
|
+
role: "alert",
|
|
2809
|
+
children: t("error.generic", { message: state.error })
|
|
2810
|
+
}),
|
|
2811
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2812
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
2813
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2814
|
+
type: "button",
|
|
2815
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2816
|
+
disabled: !enabledDirty || saving,
|
|
2817
|
+
onClick: discardEnabled,
|
|
2818
|
+
children: t("discard")
|
|
2819
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2820
|
+
type: "button",
|
|
2821
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2822
|
+
disabled: !writable || saving || !enabledDirty,
|
|
2823
|
+
onClick: saveEnabled,
|
|
2824
|
+
children: saving ? t("save.saving") : t("save")
|
|
2825
|
+
})]
|
|
2826
|
+
})
|
|
2827
|
+
] }),
|
|
2828
|
+
scalars.enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
2829
|
+
className: FallbacksCard_module_css_default.fieldset,
|
|
2830
|
+
disabled: !writable,
|
|
2831
|
+
children: [
|
|
2832
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2833
|
+
className: FallbacksCard_module_css_default.sectionHeading,
|
|
2834
|
+
id: "fallbacks-main-agent",
|
|
2835
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2836
|
+
className: FallbacksCard_module_css_default.sectionHeadingText,
|
|
2837
|
+
children: t("mainAgent.label")
|
|
2838
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2839
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
2840
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2841
|
+
type: "button",
|
|
2842
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2843
|
+
disabled: !mainDirty || saving,
|
|
2844
|
+
onClick: () => {
|
|
2845
|
+
discardSection("main");
|
|
2846
|
+
},
|
|
2847
|
+
children: t("discard")
|
|
2848
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2849
|
+
type: "button",
|
|
2850
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2851
|
+
disabled: !writable || saving || !mainDirty,
|
|
2852
|
+
onClick: () => {
|
|
2853
|
+
save("main");
|
|
2854
|
+
},
|
|
2855
|
+
children: saving ? t("save.saving") : t("save")
|
|
2856
|
+
})]
|
|
2857
|
+
})]
|
|
2858
|
+
}),
|
|
2859
|
+
validationErrors.main.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2860
|
+
className: FallbacksCard_module_css_default.error,
|
|
2861
|
+
role: "alert",
|
|
2862
|
+
children: `${t("validation.blocked")}${validationErrors.main.join("; ")}`
|
|
2863
|
+
}),
|
|
2864
|
+
lastSaveSection === "main" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2865
|
+
className: FallbacksCard_module_css_default.error,
|
|
2866
|
+
role: "alert",
|
|
2867
|
+
children: t("error.generic", { message: state.error })
|
|
2868
|
+
}),
|
|
2869
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2870
|
+
className: FallbacksCard_module_css_default.field,
|
|
2871
|
+
role: "group",
|
|
2872
|
+
"aria-labelledby": "fallbacks-time-slots",
|
|
2873
|
+
children: [
|
|
2874
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2875
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
2876
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2877
|
+
id: "fallbacks-time-slots",
|
|
2878
|
+
children: t("timeSlots.label")
|
|
2879
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2880
|
+
label: t("timeSlots.tooltip"),
|
|
2881
|
+
disabled: !writable
|
|
2882
|
+
})]
|
|
2883
|
+
}),
|
|
2884
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2885
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2886
|
+
children: t("timeSlots.hint")
|
|
2887
|
+
}),
|
|
2888
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2889
|
+
className: FallbacksCard_module_css_default.list,
|
|
2890
|
+
children: timeSlotRows.map((row, index) => {
|
|
2891
|
+
const invalidWindow = invalidSlotRows?.has(index) ?? false;
|
|
2892
|
+
const chainEmpty = row.selectors.every((selector) => selectorRowToRaw(selector) === "");
|
|
2893
|
+
const firstModel = row.selectors.map(selectorRowToRaw).find((entry) => entry !== "");
|
|
2894
|
+
const slotExpanded = !row.collapsed || !writable;
|
|
2895
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2896
|
+
className: `${FallbacksCard_module_css_default.editorCard} ${draggedSlotIndex === index ? FallbacksCard_module_css_default.slotCardDragging : ""} ${overSlotIndex === index && draggedSlotIndex !== null && draggedSlotIndex !== index ? FallbacksCard_module_css_default.slotCardOver : ""}`,
|
|
2897
|
+
onDragOver: (event) => {
|
|
2898
|
+
if (draggedSlotIndex === null) return;
|
|
2899
|
+
event.preventDefault();
|
|
2900
|
+
if (overSlotIndex !== index) setOverSlotIndex(index);
|
|
2901
|
+
},
|
|
2902
|
+
onDrop: (event) => {
|
|
2903
|
+
event.preventDefault();
|
|
2904
|
+
const from = draggedSlotIndex;
|
|
2905
|
+
setDraggedSlotIndex(null);
|
|
2906
|
+
setOverSlotIndex(null);
|
|
2907
|
+
if (from !== null && from !== index) reorderTimeSlotRow(from, index);
|
|
2908
|
+
},
|
|
2909
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2910
|
+
className: FallbacksCard_module_css_default.collapseRow,
|
|
2911
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2912
|
+
type: "button",
|
|
2913
|
+
className: FallbacksCard_module_css_default.collapseToggle,
|
|
2914
|
+
"aria-expanded": slotExpanded,
|
|
2915
|
+
"aria-label": t(slotExpanded ? "timeSlots.collapse" : "timeSlots.expand"),
|
|
2916
|
+
disabled: !writable,
|
|
2917
|
+
onClick: () => {
|
|
2918
|
+
updateTimeSlotRow(index, { collapsed: !row.collapsed });
|
|
2919
|
+
},
|
|
2920
|
+
children: [
|
|
2921
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: slotExpanded ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron }),
|
|
2922
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2923
|
+
className: FallbacksCard_module_css_default.collapseTitle,
|
|
2924
|
+
children: row.kind === "preset" ? t(`timeSlots.preset.${row.preset}.label`) : row.name !== "" ? row.name : `custom ${row.start}-${row.end}`
|
|
2925
|
+
}),
|
|
2926
|
+
row.kind === "preset" && (row.preset === "liang-peak" || row.preset === "glm-peak") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2927
|
+
className: `${FallbacksCard_module_css_default.slotTag} ${FallbacksCard_module_css_default.slotTagHighCost}`,
|
|
2928
|
+
children: t("timeSlots.preset.highCost")
|
|
2929
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2930
|
+
className: `${FallbacksCard_module_css_default.slotTag} ${FallbacksCard_module_css_default.slotTagMultiplier}`,
|
|
2931
|
+
children: t("timeSlots.preset.multiplier", { n: row.preset === "liang-peak" ? "2" : "3" })
|
|
2932
|
+
})] }),
|
|
2933
|
+
activeSlotIndex === index && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2934
|
+
className: `${FallbacksCard_module_css_default.slotTag} ${FallbacksCard_module_css_default.slotTagActive}`,
|
|
2935
|
+
children: t("timeSlots.active")
|
|
2936
|
+
}),
|
|
2937
|
+
firstModel !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2938
|
+
className: FallbacksCard_module_css_default.collapseMeta,
|
|
2939
|
+
children: firstModel
|
|
2940
|
+
})
|
|
2941
|
+
]
|
|
2942
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2943
|
+
type: "button",
|
|
2944
|
+
className: FallbacksCard_module_css_default.dragHandle,
|
|
2945
|
+
draggable: writable,
|
|
2946
|
+
"data-tip": t("timeSlots.drag"),
|
|
2947
|
+
"aria-label": t("timeSlots.drag"),
|
|
2948
|
+
disabled: !writable,
|
|
2949
|
+
onDragStart: () => {
|
|
2950
|
+
if (!writable) return;
|
|
2951
|
+
setDraggedSlotIndex(index);
|
|
2952
|
+
setOverSlotIndex(index);
|
|
2953
|
+
},
|
|
2954
|
+
onDragEnd: () => {
|
|
2955
|
+
setDraggedSlotIndex(null);
|
|
2956
|
+
setOverSlotIndex(null);
|
|
2957
|
+
},
|
|
2958
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { className: FallbacksCard_module_css_default.dragHandleIcon })
|
|
2959
|
+
})]
|
|
2960
|
+
}), slotExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2961
|
+
row.kind === "preset" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2962
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1973
2963
|
className: FallbacksCard_module_css_default.ruleGrid,
|
|
1974
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2964
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1975
2965
|
className: FallbacksCard_module_css_default.ruleCell,
|
|
1976
|
-
children: [
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1998
|
-
variant: "outline",
|
|
1999
|
-
size: "sm",
|
|
2000
|
-
disabled: !writable || saving,
|
|
2001
|
-
onClick: () => {
|
|
2002
|
-
controller.revertSeed(row.id.trim());
|
|
2003
|
-
},
|
|
2004
|
-
children: t("roles.revertPersona")
|
|
2005
|
-
})]
|
|
2006
|
-
})
|
|
2007
|
-
]
|
|
2008
|
-
})
|
|
2966
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2967
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2968
|
+
children: t("timeSlots.preset.name")
|
|
2969
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2970
|
+
className: FallbacksCard_module_css_default.slotPresetName,
|
|
2971
|
+
children: t(`timeSlots.preset.${row.preset}.label`)
|
|
2972
|
+
})]
|
|
2973
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2974
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
2975
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2976
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2977
|
+
children: t("timeSlots.preset.windowLabel")
|
|
2978
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2979
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2980
|
+
children: t(`timeSlots.preset.${row.preset}.window`)
|
|
2981
|
+
})]
|
|
2982
|
+
})]
|
|
2983
|
+
}),
|
|
2984
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2985
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2986
|
+
children: t("timeSlots.preset.chainsOnly")
|
|
2009
2987
|
}),
|
|
2988
|
+
(row.preset === "glm-peak" || row.preset === "glm-valley") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2989
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2990
|
+
children: t("timeSlots.preset.glm.note")
|
|
2991
|
+
})
|
|
2992
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2010
2993
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2011
|
-
className: FallbacksCard_module_css_default.
|
|
2012
|
-
children: [
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2994
|
+
className: FallbacksCard_module_css_default.field,
|
|
2995
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2996
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2997
|
+
children: t("timeSlots.name")
|
|
2998
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2999
|
+
className: FallbacksCard_module_css_default.input,
|
|
3000
|
+
value: row.name,
|
|
3001
|
+
placeholder: t("timeSlots.name"),
|
|
3002
|
+
"aria-label": t("timeSlots.name"),
|
|
2016
3003
|
disabled: !writable,
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
updateRoleSelector(index, selectorIndex, patch);
|
|
2020
|
-
},
|
|
2021
|
-
onRemove: () => {
|
|
2022
|
-
removeRoleSelector(index, selectorIndex);
|
|
3004
|
+
onChange: (event) => {
|
|
3005
|
+
updateTimeSlotRow(index, { name: event.target.value });
|
|
2023
3006
|
}
|
|
2024
|
-
}
|
|
3007
|
+
})]
|
|
3008
|
+
}),
|
|
3009
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3010
|
+
className: FallbacksCard_module_css_default.field,
|
|
3011
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3012
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3013
|
+
children: t("timeSlots.tz.label")
|
|
3014
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2025
3015
|
className: FallbacksCard_module_css_default.hint,
|
|
2026
|
-
|
|
3016
|
+
"aria-label": t("timeSlots.tz.label"),
|
|
3017
|
+
children: tzDisplayLabel(presetsPresent ? "Asia/Shanghai" : hostTimeZone())
|
|
2027
3018
|
})]
|
|
2028
3019
|
}),
|
|
2029
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3020
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2030
3021
|
className: FallbacksCard_module_css_default.ruleGrid,
|
|
2031
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
3022
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2032
3023
|
className: FallbacksCard_module_css_default.ruleCell,
|
|
2033
3024
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2034
3025
|
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2035
|
-
children: t("
|
|
2036
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2037
|
-
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.
|
|
2038
|
-
value: row.
|
|
2039
|
-
|
|
3026
|
+
children: t("timeSlots.start")
|
|
3027
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3028
|
+
className: `${FallbacksCard_module_css_default.input} ${invalidWindow ? FallbacksCard_module_css_default.inputInvalid : ""}`,
|
|
3029
|
+
value: row.start,
|
|
3030
|
+
placeholder: "09:00",
|
|
3031
|
+
"aria-label": t("timeSlots.start"),
|
|
2040
3032
|
disabled: !writable,
|
|
2041
3033
|
onChange: (event) => {
|
|
2042
|
-
|
|
2043
|
-
}
|
|
2044
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2045
|
-
value: "inherit-root",
|
|
2046
|
-
children: t("roles.fallback.inherit-root")
|
|
2047
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2048
|
-
value: "none",
|
|
2049
|
-
children: t("roles.fallback.none")
|
|
2050
|
-
})]
|
|
3034
|
+
updateTimeSlotRow(index, { start: event.target.value });
|
|
3035
|
+
}
|
|
2051
3036
|
})]
|
|
2052
|
-
})
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
3037
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3038
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3039
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3040
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3041
|
+
children: t("timeSlots.end")
|
|
3042
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3043
|
+
className: `${FallbacksCard_module_css_default.input} ${invalidWindow ? FallbacksCard_module_css_default.inputInvalid : ""}`,
|
|
3044
|
+
value: row.end,
|
|
3045
|
+
placeholder: "18:00",
|
|
3046
|
+
"aria-label": t("timeSlots.end"),
|
|
3047
|
+
disabled: !writable,
|
|
3048
|
+
onChange: (event) => {
|
|
3049
|
+
updateTimeSlotRow(index, { end: event.target.value });
|
|
3050
|
+
}
|
|
3051
|
+
})]
|
|
3052
|
+
})]
|
|
2063
3053
|
}),
|
|
2064
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2065
|
-
className: FallbacksCard_module_css_default.cardFoot,
|
|
2066
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2067
|
-
type: "button",
|
|
2068
|
-
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
2069
|
-
"data-tip": t("roles.remove"),
|
|
2070
|
-
"aria-label": t("roles.remove"),
|
|
2071
|
-
onClick: () => {
|
|
2072
|
-
removeRole(index);
|
|
2073
|
-
},
|
|
2074
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
2075
|
-
})
|
|
2076
|
-
})
|
|
2077
|
-
]
|
|
2078
|
-
}, index);
|
|
2079
|
-
})
|
|
2080
|
-
}),
|
|
2081
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2082
|
-
variant: "outline",
|
|
2083
|
-
size: "sm",
|
|
2084
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
2085
|
-
className: FallbacksCard_module_css_default.addButton,
|
|
2086
|
-
onClick: addRole,
|
|
2087
|
-
children: t("roles.add")
|
|
2088
|
-
})
|
|
2089
|
-
]
|
|
2090
|
-
}),
|
|
2091
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2092
|
-
className: FallbacksCard_module_css_default.field,
|
|
2093
|
-
role: "group",
|
|
2094
|
-
"aria-labelledby": "fallbacks-roles-rules",
|
|
2095
|
-
children: [
|
|
2096
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2097
|
-
className: FallbacksCard_module_css_default.fieldLabel,
|
|
2098
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2099
|
-
id: "fallbacks-roles-rules",
|
|
2100
|
-
children: t("roles.rules")
|
|
2101
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2102
|
-
label: t("roles.rules.tooltip"),
|
|
2103
|
-
disabled: !writable
|
|
2104
|
-
})]
|
|
2105
|
-
}),
|
|
2106
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2107
|
-
className: FallbacksCard_module_css_default.hint,
|
|
2108
|
-
children: t("roles.rules.hint")
|
|
2109
|
-
}),
|
|
2110
|
-
state.catalogStatus === "error" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2111
|
-
className: FallbacksCard_module_css_default.hint,
|
|
2112
|
-
children: t("catalog.error", { message: state.catalogError })
|
|
2113
|
-
}),
|
|
2114
|
-
state.catalogStatus === "ready" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2115
|
-
className: FallbacksCard_module_css_default.hint,
|
|
2116
|
-
children: t("catalog.partial", { message: state.catalogError })
|
|
2117
|
-
}),
|
|
2118
|
-
state.catalogStatus === "ready" && (state.groups.length === 0 || state.configuredProviders.length === 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2119
|
-
className: FallbacksCard_module_css_default.hint,
|
|
2120
|
-
children: t("catalog.empty")
|
|
2121
|
-
}),
|
|
2122
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2123
|
-
className: FallbacksCard_module_css_default.list,
|
|
2124
|
-
children: ruleRows.map((row, index) => {
|
|
2125
|
-
const catalog = catalogOf(state);
|
|
2126
|
-
const providerRaw = selectionToRaw(row.provider);
|
|
2127
|
-
const group = catalog?.groups.find((entry) => entry.id === providerRaw);
|
|
2128
|
-
const providerOutside = row.provider?.kind === "outside";
|
|
2129
|
-
const providerUnconfigured = !providerOutside && providerRaw !== "" && (catalog?.providers.some((entry) => entry.provider === providerRaw) ?? false) && !state.configuredProviders.some((entry) => entry.provider === providerRaw);
|
|
2130
|
-
const modelOutside = row.model?.kind === "outside";
|
|
2131
|
-
const roleOutside = row.role !== "" && !roleOptions.includes(row.role);
|
|
2132
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2133
|
-
className: FallbacksCard_module_css_default.editorCard,
|
|
2134
|
-
children: [
|
|
2135
3054
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2136
|
-
className: FallbacksCard_module_css_default.
|
|
3055
|
+
className: FallbacksCard_module_css_default.field,
|
|
2137
3056
|
children: [
|
|
2138
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2139
|
-
className: FallbacksCard_module_css_default.
|
|
2140
|
-
children:
|
|
2141
|
-
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2142
|
-
children: t("roles.rule.origin")
|
|
2143
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
2144
|
-
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
2145
|
-
value: row.origin,
|
|
2146
|
-
onChange: (event) => {
|
|
2147
|
-
updateRuleRow(index, { origin: event.target.value });
|
|
2148
|
-
},
|
|
2149
|
-
children: [
|
|
2150
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2151
|
-
value: "",
|
|
2152
|
-
children: t("roles.rule.origin.any")
|
|
2153
|
-
}),
|
|
2154
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2155
|
-
value: "root",
|
|
2156
|
-
children: t("roles.rule.origin.root")
|
|
2157
|
-
}),
|
|
2158
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2159
|
-
value: "subagent",
|
|
2160
|
-
children: t("roles.rule.origin.subagent")
|
|
2161
|
-
})
|
|
2162
|
-
]
|
|
2163
|
-
})]
|
|
2164
|
-
}),
|
|
2165
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2166
|
-
className: FallbacksCard_module_css_default.ruleCell,
|
|
2167
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2168
|
-
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2169
|
-
children: t("roles.rule.provider")
|
|
2170
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
2171
|
-
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
2172
|
-
value: providerRaw,
|
|
2173
|
-
onChange: (event) => {
|
|
2174
|
-
if (event.target.value === providerRaw) return;
|
|
2175
|
-
updateRuleRow(index, {
|
|
2176
|
-
provider: classifyProvider(event.target.value, catalog),
|
|
2177
|
-
model: null
|
|
2178
|
-
});
|
|
2179
|
-
},
|
|
2180
|
-
children: [
|
|
2181
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2182
|
-
value: "",
|
|
2183
|
-
children: t("roles.rule.provider.any")
|
|
2184
|
-
}),
|
|
2185
|
-
state.configuredProviders.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2186
|
-
value: entry.provider,
|
|
2187
|
-
children: entry.displayName
|
|
2188
|
-
}, entry.provider)),
|
|
2189
|
-
providerUnconfigured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2190
|
-
value: providerRaw,
|
|
2191
|
-
children: `${providerRaw}${t("catalog.unconfigured.short")}`
|
|
2192
|
-
}),
|
|
2193
|
-
providerOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2194
|
-
value: providerRaw,
|
|
2195
|
-
children: `${providerRaw}${t("catalog.outside.short")}`
|
|
2196
|
-
})
|
|
2197
|
-
]
|
|
2198
|
-
})]
|
|
3057
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3058
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3059
|
+
children: t("timeSlots.days")
|
|
2199
3060
|
}),
|
|
2200
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2201
|
-
className: FallbacksCard_module_css_default.
|
|
2202
|
-
children:
|
|
2203
|
-
className: FallbacksCard_module_css_default.
|
|
2204
|
-
children:
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
value: "",
|
|
2214
|
-
children: t("roles.rule.model.any")
|
|
2215
|
-
}),
|
|
2216
|
-
(group?.models ?? []).map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2217
|
-
value: model.id,
|
|
2218
|
-
children: model.name
|
|
2219
|
-
}, model.id)),
|
|
2220
|
-
modelOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2221
|
-
value: selectionToRaw(row.model),
|
|
2222
|
-
children: `${selectionToRaw(row.model)}${t("catalog.outside.short")}`
|
|
2223
|
-
})
|
|
2224
|
-
]
|
|
2225
|
-
})]
|
|
3061
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3062
|
+
className: FallbacksCard_module_css_default.dayRow,
|
|
3063
|
+
children: SLOT_WEEKDAYS.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3064
|
+
className: FallbacksCard_module_css_default.dayCell,
|
|
3065
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3066
|
+
type: "checkbox",
|
|
3067
|
+
checked: row.days.includes(dayIndex),
|
|
3068
|
+
disabled: !writable,
|
|
3069
|
+
onChange: () => {
|
|
3070
|
+
updateTimeSlotRow(index, { days: row.days.includes(dayIndex) ? row.days.filter((existing) => existing !== dayIndex) : [...row.days, dayIndex] });
|
|
3071
|
+
}
|
|
3072
|
+
}), t(`timeSlots.day.${day}`)]
|
|
3073
|
+
}, day))
|
|
2226
3074
|
}),
|
|
2227
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2228
|
-
className: FallbacksCard_module_css_default.
|
|
2229
|
-
children:
|
|
2230
|
-
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2231
|
-
children: t("roles.rule.role")
|
|
2232
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
2233
|
-
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
2234
|
-
value: row.role,
|
|
2235
|
-
disabled: !writable,
|
|
2236
|
-
onChange: (event) => {
|
|
2237
|
-
updateRuleRow(index, { role: event.target.value });
|
|
2238
|
-
},
|
|
2239
|
-
children: [
|
|
2240
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2241
|
-
value: "",
|
|
2242
|
-
children: t("roles.rule.roleSelectPlaceholder")
|
|
2243
|
-
}),
|
|
2244
|
-
roleOptions.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2245
|
-
value: id,
|
|
2246
|
-
children: id === "inherit" ? t("roles.rule.role.inherit") : id
|
|
2247
|
-
}, id)),
|
|
2248
|
-
roleOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2249
|
-
value: row.role,
|
|
2250
|
-
children: `${row.role}${t("roles.rule.roleUndeclared.short")}`
|
|
2251
|
-
})
|
|
2252
|
-
]
|
|
2253
|
-
})]
|
|
3075
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3076
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3077
|
+
children: t("timeSlots.days.hint")
|
|
2254
3078
|
})
|
|
2255
3079
|
]
|
|
2256
3080
|
}),
|
|
2257
|
-
(
|
|
2258
|
-
className: FallbacksCard_module_css_default.hint,
|
|
2259
|
-
children: [t("catalog.outside.hint"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2260
|
-
label: t("catalog.outside.tooltip"),
|
|
2261
|
-
disabled: !writable
|
|
2262
|
-
})]
|
|
2263
|
-
}),
|
|
2264
|
-
row.role === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3081
|
+
(row.start !== "" || row.end !== "") && !(HHMM_RE.test(row.start) && HHMM_RE.test(row.end)) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2265
3082
|
className: FallbacksCard_module_css_default.hint,
|
|
2266
|
-
children: t("validation.
|
|
2267
|
-
}),
|
|
2268
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2269
|
-
className: FallbacksCard_module_css_default.cardFoot,
|
|
2270
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2271
|
-
type: "button",
|
|
2272
|
-
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
2273
|
-
"data-tip": t("roles.removeRule"),
|
|
2274
|
-
"aria-label": t("roles.removeRule"),
|
|
2275
|
-
onClick: () => {
|
|
2276
|
-
setRuleRows((rows) => rows.filter((_, rowIndex) => rowIndex !== index));
|
|
2277
|
-
},
|
|
2278
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
2279
|
-
})
|
|
3083
|
+
children: t("validation.slotWindow")
|
|
2280
3084
|
})
|
|
2281
|
-
]
|
|
2282
|
-
|
|
2283
|
-
})
|
|
2284
|
-
}),
|
|
2285
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2286
|
-
variant: "outline",
|
|
2287
|
-
size: "sm",
|
|
2288
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
2289
|
-
className: FallbacksCard_module_css_default.addButton,
|
|
2290
|
-
onClick: () => {
|
|
2291
|
-
setRuleRows((rows) => [...rows, {
|
|
2292
|
-
origin: "",
|
|
2293
|
-
provider: null,
|
|
2294
|
-
model: null,
|
|
2295
|
-
role: ""
|
|
2296
|
-
}]);
|
|
2297
|
-
},
|
|
2298
|
-
children: t("roles.addRule")
|
|
2299
|
-
})
|
|
2300
|
-
]
|
|
2301
|
-
}),
|
|
2302
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2303
|
-
className: FallbacksCard_module_css_default.field,
|
|
2304
|
-
role: "group",
|
|
2305
|
-
"aria-labelledby": "fallbacks-advanced",
|
|
2306
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2307
|
-
type: "button",
|
|
2308
|
-
className: FallbacksCard_module_css_default.sectionToggle,
|
|
2309
|
-
disabled: !writable,
|
|
2310
|
-
"aria-expanded": advancedVisible,
|
|
2311
|
-
"aria-controls": advancedVisible ? "fallbacks-advanced-body" : void 0,
|
|
2312
|
-
"aria-label": t(advancedVisible ? "advanced.collapse" : "advanced.expand"),
|
|
2313
|
-
onClick: () => {
|
|
2314
|
-
if (writable) setAdvancedOpen(!advancedOpen);
|
|
2315
|
-
},
|
|
2316
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2317
|
-
id: "fallbacks-advanced",
|
|
2318
|
-
className: FallbacksCard_module_css_default.sectionToggleText,
|
|
2319
|
-
children: t("advanced.label")
|
|
2320
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: advancedVisible ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron })]
|
|
2321
|
-
}), advancedVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2322
|
-
id: "fallbacks-advanced-body",
|
|
2323
|
-
children: [
|
|
2324
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2325
|
-
className: FallbacksCard_module_css_default.checkboxRow,
|
|
2326
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2327
|
-
className: FallbacksCard_module_css_default.checkLabel,
|
|
2328
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2329
|
-
className: FallbacksCard_module_css_default.checkLabelTitle,
|
|
2330
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
2331
|
-
htmlFor: "fallbacks-role-automatch",
|
|
2332
|
-
children: t("roleAutoMatch.label")
|
|
2333
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2334
|
-
label: t("roleAutoMatch.tooltip"),
|
|
2335
|
-
disabled: !writable
|
|
2336
|
-
})]
|
|
2337
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2338
|
-
className: FallbacksCard_module_css_default.checkLabelDesc,
|
|
2339
|
-
children: t("roleAutoMatch.hint")
|
|
2340
|
-
})]
|
|
2341
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2342
|
-
id: "fallbacks-role-automatch",
|
|
2343
|
-
type: "checkbox",
|
|
2344
|
-
className: FallbacksCard_module_css_default.checkbox,
|
|
2345
|
-
checked: scalars.roleAutoMatch,
|
|
2346
|
-
disabled: !writable,
|
|
2347
|
-
onChange: (event) => {
|
|
2348
|
-
updateScalars((draft) => {
|
|
2349
|
-
draft.roleAutoMatch = event.target.checked;
|
|
2350
|
-
});
|
|
2351
|
-
}
|
|
2352
|
-
})]
|
|
2353
|
-
}),
|
|
2354
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2355
|
-
className: FallbacksCard_module_css_default.field,
|
|
2356
|
-
role: "group",
|
|
2357
|
-
"aria-labelledby": "fallbacks-trigger-codes",
|
|
2358
|
-
children: [
|
|
2359
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2360
|
-
className: FallbacksCard_module_css_default.fieldLabel,
|
|
2361
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2362
|
-
id: "fallbacks-trigger-codes",
|
|
2363
|
-
children: t("triggerCodes.label")
|
|
2364
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2365
|
-
label: t("triggerCodes.tooltip"),
|
|
2366
|
-
disabled: !writable
|
|
2367
|
-
})]
|
|
2368
|
-
}),
|
|
2369
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3085
|
+
] }),
|
|
3086
|
+
chainEmpty && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2370
3087
|
className: FallbacksCard_module_css_default.hint,
|
|
2371
|
-
children: t("
|
|
3088
|
+
children: t("validation.slotChainRequired")
|
|
2372
3089
|
}),
|
|
2373
|
-
|
|
2374
|
-
className: FallbacksCard_module_css_default.
|
|
2375
|
-
children:
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
3090
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3091
|
+
className: FallbacksCard_module_css_default.chainSelectors,
|
|
3092
|
+
children: row.selectors.map((selector, selectorIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChainSelectorEditor, {
|
|
3093
|
+
selector,
|
|
3094
|
+
catalog: catalogOf(state),
|
|
3095
|
+
configuredProviders: state.configuredProviders,
|
|
3096
|
+
disabled: !writable,
|
|
3097
|
+
t,
|
|
3098
|
+
onChange: (patch) => {
|
|
3099
|
+
updateTimeSlotSelector(index, selectorIndex, patch);
|
|
3100
|
+
},
|
|
3101
|
+
onRemove: () => {
|
|
3102
|
+
removeTimeSlotSelector(index, selectorIndex);
|
|
2382
3103
|
}
|
|
2383
|
-
}
|
|
2384
|
-
}, code)),
|
|
2385
|
-
unknownCodes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2386
|
-
className: FallbacksCard_module_css_default.hint,
|
|
2387
|
-
children: t("triggerCodes.extra", { codes: unknownCodes.join(", ") })
|
|
2388
|
-
})
|
|
2389
|
-
]
|
|
2390
|
-
}),
|
|
2391
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2392
|
-
className: FallbacksCard_module_css_default.field,
|
|
2393
|
-
role: "group",
|
|
2394
|
-
"aria-labelledby": "fallbacks-revert-policy",
|
|
2395
|
-
children: [
|
|
2396
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2397
|
-
className: FallbacksCard_module_css_default.fieldLabel,
|
|
2398
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2399
|
-
id: "fallbacks-revert-policy",
|
|
2400
|
-
children: t("revertPolicy.label")
|
|
2401
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2402
|
-
label: t("revertPolicy.tooltip"),
|
|
2403
|
-
disabled: !writable
|
|
2404
|
-
})]
|
|
3104
|
+
}, selectorIndex))
|
|
2405
3105
|
}),
|
|
2406
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2407
|
-
|
|
2408
|
-
|
|
3106
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3107
|
+
variant: "outline",
|
|
3108
|
+
size: "sm",
|
|
3109
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3110
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3111
|
+
onClick: () => {
|
|
3112
|
+
addTimeSlotSelector(index);
|
|
3113
|
+
},
|
|
3114
|
+
children: t("timeSlots.selector.add")
|
|
2409
3115
|
}),
|
|
2410
|
-
|
|
2411
|
-
className: FallbacksCard_module_css_default.
|
|
2412
|
-
children:
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
3116
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3117
|
+
className: FallbacksCard_module_css_default.cardFoot,
|
|
3118
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3119
|
+
className: FallbacksCard_module_css_default.rowActions,
|
|
3120
|
+
children: [
|
|
3121
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3122
|
+
type: "button",
|
|
3123
|
+
className: FallbacksCard_module_css_default.iconButton,
|
|
3124
|
+
"data-tip": t("timeSlots.moveUp"),
|
|
3125
|
+
"aria-label": t("timeSlots.moveUp"),
|
|
3126
|
+
disabled: !writable || index === 0,
|
|
3127
|
+
onClick: () => {
|
|
3128
|
+
moveTimeSlotRow(index, -1);
|
|
3129
|
+
},
|
|
3130
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, {})
|
|
3131
|
+
}),
|
|
3132
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3133
|
+
type: "button",
|
|
3134
|
+
className: FallbacksCard_module_css_default.iconButton,
|
|
3135
|
+
"data-tip": t("timeSlots.moveDown"),
|
|
3136
|
+
"aria-label": t("timeSlots.moveDown"),
|
|
3137
|
+
disabled: !writable || index === timeSlotRows.length - 1,
|
|
3138
|
+
onClick: () => {
|
|
3139
|
+
moveTimeSlotRow(index, 1);
|
|
3140
|
+
},
|
|
3141
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})
|
|
3142
|
+
}),
|
|
3143
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3144
|
+
type: "button",
|
|
3145
|
+
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
3146
|
+
"data-tip": t("timeSlots.remove"),
|
|
3147
|
+
"aria-label": t("timeSlots.remove"),
|
|
3148
|
+
onClick: () => {
|
|
3149
|
+
removeTimeSlotRow(index);
|
|
3150
|
+
},
|
|
3151
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
3152
|
+
})
|
|
3153
|
+
]
|
|
3154
|
+
})
|
|
3155
|
+
})
|
|
3156
|
+
] })]
|
|
3157
|
+
}, index);
|
|
3158
|
+
})
|
|
3159
|
+
}),
|
|
3160
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3161
|
+
className: FallbacksCard_module_css_default.slotAddRow,
|
|
3162
|
+
children: [
|
|
3163
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3164
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3165
|
+
value: presetToAdd,
|
|
3166
|
+
"aria-label": t("timeSlots.presetPlaceholder"),
|
|
3167
|
+
disabled: !writable,
|
|
3168
|
+
onChange: (event) => {
|
|
3169
|
+
setPresetToAdd(event.target.value);
|
|
3170
|
+
},
|
|
3171
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3172
|
+
value: "",
|
|
3173
|
+
children: t("timeSlots.presetPlaceholder")
|
|
3174
|
+
}), SLOT_PRESET_IDS.filter((id) => !timeSlotRows.some((row) => row.kind === "preset" && row.preset === id)).map((id) => {
|
|
3175
|
+
const glmUnconfigured = !glmConfigured && (id === "glm-peak" || id === "glm-valley");
|
|
3176
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
3177
|
+
value: id,
|
|
3178
|
+
disabled: glmUnconfigured,
|
|
3179
|
+
children: [t(`timeSlots.preset.${id}.label`), glmUnconfigured ? t("timeSlots.preset.glm.unconfigured") : null]
|
|
3180
|
+
}, id);
|
|
3181
|
+
})]
|
|
2424
3182
|
}),
|
|
2425
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
3183
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3184
|
+
variant: "outline",
|
|
3185
|
+
size: "sm",
|
|
3186
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3187
|
+
disabled: !writable || presetToAdd === "",
|
|
3188
|
+
onClick: addPresetSlotRow,
|
|
3189
|
+
children: t("timeSlots.addPreset")
|
|
3190
|
+
}),
|
|
3191
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3192
|
+
variant: "outline",
|
|
3193
|
+
size: "sm",
|
|
3194
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3195
|
+
disabled: !writable,
|
|
3196
|
+
onClick: addCustomSlotRow,
|
|
3197
|
+
children: t("timeSlots.addCustom")
|
|
3198
|
+
})
|
|
3199
|
+
]
|
|
3200
|
+
})
|
|
3201
|
+
]
|
|
3202
|
+
}),
|
|
3203
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3204
|
+
className: FallbacksCard_module_css_default.field,
|
|
3205
|
+
role: "group",
|
|
3206
|
+
"aria-labelledby": "fallbacks-root-chain",
|
|
3207
|
+
children: [
|
|
3208
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3209
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3210
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3211
|
+
id: "fallbacks-root-chain",
|
|
3212
|
+
children: t("rootChain.label")
|
|
3213
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3214
|
+
label: t("rootChain.tooltip"),
|
|
3215
|
+
disabled: !writable
|
|
3216
|
+
})]
|
|
3217
|
+
}),
|
|
3218
|
+
state.catalogStatus === "error" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3219
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3220
|
+
children: t("catalog.error", { message: state.catalogError })
|
|
3221
|
+
}),
|
|
3222
|
+
state.catalogStatus === "ready" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3223
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3224
|
+
children: t("catalog.partial", { message: state.catalogError })
|
|
3225
|
+
}),
|
|
3226
|
+
state.catalogStatus === "ready" && (state.groups.length === 0 || state.configuredProviders.length === 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3227
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3228
|
+
children: t("catalog.empty")
|
|
3229
|
+
}),
|
|
3230
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3231
|
+
className: FallbacksCard_module_css_default.list,
|
|
3232
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3233
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3234
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3235
|
+
className: FallbacksCard_module_css_default.chainSelectors,
|
|
3236
|
+
children: allDayChainRow.selectors.map((selector, selectorIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChainSelectorEditor, {
|
|
3237
|
+
selector,
|
|
3238
|
+
catalog: catalogOf(state),
|
|
3239
|
+
configuredProviders: state.configuredProviders,
|
|
3240
|
+
disabled: !writable,
|
|
3241
|
+
t,
|
|
3242
|
+
onChange: (patch) => {
|
|
3243
|
+
updateAllDayChainSelector(selectorIndex, patch);
|
|
3244
|
+
},
|
|
3245
|
+
onRemove: () => {
|
|
3246
|
+
removeAllDayChainSelector(selectorIndex);
|
|
3247
|
+
}
|
|
3248
|
+
}, selectorIndex))
|
|
3249
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3250
|
+
variant: "outline",
|
|
3251
|
+
size: "sm",
|
|
3252
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3253
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3254
|
+
onClick: addAllDayChainSelector,
|
|
3255
|
+
children: t("timeSlots.selector.add")
|
|
3256
|
+
})]
|
|
3257
|
+
})
|
|
3258
|
+
})
|
|
3259
|
+
]
|
|
3260
|
+
}),
|
|
3261
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3262
|
+
className: FallbacksCard_module_css_default.field,
|
|
3263
|
+
role: "group",
|
|
3264
|
+
"aria-labelledby": "fallbacks-default-model",
|
|
3265
|
+
children: [
|
|
3266
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3267
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3268
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3269
|
+
id: "fallbacks-default-model",
|
|
3270
|
+
children: t("defaultModel.label")
|
|
3271
|
+
})
|
|
3272
|
+
}),
|
|
3273
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3274
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3275
|
+
children: t("allDay.hint")
|
|
3276
|
+
}),
|
|
3277
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3278
|
+
className: FallbacksCard_module_css_default.list,
|
|
3279
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3280
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3281
|
+
children: [
|
|
3282
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3283
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3284
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3285
|
+
type: "radio",
|
|
3286
|
+
name: "fallbacks-all-day",
|
|
3287
|
+
checked: allDayModel === ALL_DAY_FLASH,
|
|
3288
|
+
disabled: !writable,
|
|
3289
|
+
onChange: () => {
|
|
3290
|
+
setAllDayModel(ALL_DAY_FLASH);
|
|
3291
|
+
}
|
|
3292
|
+
}), t("allDay.flash")]
|
|
3293
|
+
}),
|
|
3294
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3295
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3296
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3297
|
+
type: "radio",
|
|
3298
|
+
name: "fallbacks-all-day",
|
|
3299
|
+
checked: allDayModel === ALL_DAY_PRO,
|
|
3300
|
+
disabled: !writable,
|
|
3301
|
+
onChange: () => {
|
|
3302
|
+
setAllDayModel(ALL_DAY_PRO);
|
|
3303
|
+
}
|
|
3304
|
+
}), t("allDay.pro")]
|
|
3305
|
+
}),
|
|
3306
|
+
allDayModel === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3307
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3308
|
+
children: t("allDay.nonconforming")
|
|
3309
|
+
})
|
|
3310
|
+
]
|
|
3311
|
+
})
|
|
3312
|
+
})
|
|
3313
|
+
]
|
|
3314
|
+
}),
|
|
3315
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3316
|
+
className: FallbacksCard_module_css_default.sectionHeading,
|
|
3317
|
+
id: "fallbacks-subagents",
|
|
3318
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3319
|
+
className: FallbacksCard_module_css_default.sectionHeadingText,
|
|
3320
|
+
children: t("subagents.label")
|
|
3321
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3322
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
3323
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3324
|
+
type: "button",
|
|
3325
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
3326
|
+
disabled: !subDirty || saving,
|
|
3327
|
+
onClick: () => {
|
|
3328
|
+
discardSection("sub");
|
|
3329
|
+
},
|
|
3330
|
+
children: t("discard")
|
|
3331
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3332
|
+
type: "button",
|
|
3333
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
3334
|
+
disabled: !writable || saving || !subDirty,
|
|
3335
|
+
onClick: () => {
|
|
3336
|
+
save("sub");
|
|
3337
|
+
},
|
|
3338
|
+
children: saving ? t("save.saving") : t("save")
|
|
3339
|
+
})]
|
|
3340
|
+
})]
|
|
3341
|
+
}),
|
|
3342
|
+
validationErrors.sub.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3343
|
+
className: FallbacksCard_module_css_default.error,
|
|
3344
|
+
role: "alert",
|
|
3345
|
+
children: `${t("validation.blocked")}${validationErrors.sub.join("; ")}`
|
|
3346
|
+
}),
|
|
3347
|
+
lastSaveSection === "sub" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3348
|
+
className: FallbacksCard_module_css_default.error,
|
|
3349
|
+
role: "alert",
|
|
3350
|
+
children: t("error.generic", { message: state.error })
|
|
3351
|
+
}),
|
|
3352
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3353
|
+
className: FallbacksCard_module_css_default.field,
|
|
3354
|
+
role: "group",
|
|
3355
|
+
"aria-labelledby": "fallbacks-roles-list",
|
|
3356
|
+
children: [
|
|
3357
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3358
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3359
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3360
|
+
id: "fallbacks-roles-list",
|
|
3361
|
+
children: t("roles.list.label")
|
|
3362
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3363
|
+
label: t("roles.list.tooltip"),
|
|
3364
|
+
disabled: !writable
|
|
3365
|
+
})]
|
|
3366
|
+
}),
|
|
3367
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3368
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3369
|
+
children: t("roles.list.hint")
|
|
3370
|
+
}),
|
|
3371
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3372
|
+
className: FallbacksCard_module_css_default.list,
|
|
3373
|
+
children: roleRows.map((row, index) => {
|
|
3374
|
+
const invalid = invalidRoleIds?.has(row.id.trim()) ?? false;
|
|
3375
|
+
const seed = seededIds.get(row.id.trim());
|
|
3376
|
+
const roleSummary = row.selectors.map(selectorRowToRaw).find((entry) => entry !== "") ?? row.fallback;
|
|
3377
|
+
const roleExpanded = !row.collapsed || !writable;
|
|
3378
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3379
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3380
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3381
|
+
className: FallbacksCard_module_css_default.collapseRow,
|
|
3382
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3383
|
+
type: "button",
|
|
3384
|
+
className: FallbacksCard_module_css_default.collapseToggle,
|
|
3385
|
+
"aria-expanded": roleExpanded,
|
|
3386
|
+
"aria-label": t(roleExpanded ? "roles.collapse" : "roles.expand"),
|
|
3387
|
+
disabled: !writable,
|
|
3388
|
+
onClick: () => {
|
|
3389
|
+
updateRoleRow(index, { collapsed: !row.collapsed });
|
|
3390
|
+
},
|
|
2430
3391
|
children: [
|
|
2431
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
htmlFor: "fallbacks-cooldown-ms",
|
|
2436
|
-
children: t("cooldownMs.label")
|
|
2437
|
-
}),
|
|
2438
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2439
|
-
label: t("cooldownMs.tooltip"),
|
|
2440
|
-
disabled: !writable
|
|
2441
|
-
}),
|
|
2442
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2443
|
-
className: FallbacksCard_module_css_default.defaultNote,
|
|
2444
|
-
children: [
|
|
2445
|
-
t("defaults.prefix"),
|
|
2446
|
-
": ",
|
|
2447
|
-
state.config.cooldownMs
|
|
2448
|
-
]
|
|
2449
|
-
})
|
|
2450
|
-
]
|
|
2451
|
-
}),
|
|
2452
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2453
|
-
id: "fallbacks-cooldown-ms",
|
|
2454
|
-
className: FallbacksCard_module_css_default.input,
|
|
2455
|
-
type: "number",
|
|
2456
|
-
min: 0,
|
|
2457
|
-
value: String(scalars.cooldownMs),
|
|
2458
|
-
disabled: !writable,
|
|
2459
|
-
onChange: (event) => {
|
|
2460
|
-
updateScalars((draft) => {
|
|
2461
|
-
draft.cooldownMs = parseCount(event.target.value);
|
|
2462
|
-
});
|
|
2463
|
-
}
|
|
3392
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: roleExpanded ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron }),
|
|
3393
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3394
|
+
className: FallbacksCard_module_css_default.collapseTitle,
|
|
3395
|
+
children: row.id
|
|
2464
3396
|
}),
|
|
2465
3397
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2466
|
-
className: FallbacksCard_module_css_default.
|
|
2467
|
-
children:
|
|
3398
|
+
className: FallbacksCard_module_css_default.collapseMeta,
|
|
3399
|
+
children: roleSummary
|
|
2468
3400
|
})
|
|
2469
3401
|
]
|
|
3402
|
+
})
|
|
3403
|
+
}), roleExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3404
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3405
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3406
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3407
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3408
|
+
children: [
|
|
3409
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3410
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3411
|
+
children: t("roles.id")
|
|
3412
|
+
}),
|
|
3413
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3414
|
+
className: `${FallbacksCard_module_css_default.input} ${invalid ? FallbacksCard_module_css_default.inputInvalid : ""}`,
|
|
3415
|
+
value: row.id,
|
|
3416
|
+
placeholder: t("roles.idPlaceholder"),
|
|
3417
|
+
"aria-label": t("roles.id"),
|
|
3418
|
+
"aria-invalid": invalid ? true : void 0,
|
|
3419
|
+
disabled: !writable || seed !== void 0,
|
|
3420
|
+
onChange: (event) => {
|
|
3421
|
+
updateRoleRow(index, { id: event.target.value });
|
|
3422
|
+
}
|
|
3423
|
+
}),
|
|
3424
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3425
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3426
|
+
children: t("roles.id.hint")
|
|
3427
|
+
})
|
|
3428
|
+
]
|
|
3429
|
+
})
|
|
3430
|
+
}),
|
|
3431
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3432
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3433
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3434
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3435
|
+
children: [
|
|
3436
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3437
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3438
|
+
children: t("roles.persona")
|
|
3439
|
+
}),
|
|
3440
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
3441
|
+
rows: 3,
|
|
3442
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.inputTextarea}`,
|
|
3443
|
+
value: row.persona,
|
|
3444
|
+
placeholder: t("roles.personaPlaceholder"),
|
|
3445
|
+
"aria-label": t("roles.persona"),
|
|
3446
|
+
disabled: !writable,
|
|
3447
|
+
onChange: (event) => {
|
|
3448
|
+
updateRoleRow(index, { persona: event.target.value });
|
|
3449
|
+
}
|
|
3450
|
+
}),
|
|
3451
|
+
seed !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3452
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3453
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3454
|
+
className: FallbacksCard_module_css_default.pending,
|
|
3455
|
+
children: t(seed ? "roles.seedOverride" : "roles.seedDefault")
|
|
3456
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3457
|
+
variant: "outline",
|
|
3458
|
+
size: "sm",
|
|
3459
|
+
disabled: !writable || saving,
|
|
3460
|
+
onClick: () => {
|
|
3461
|
+
forceReseed.current = true;
|
|
3462
|
+
controller.revertSeed(row.id.trim()).then((persona) => {
|
|
3463
|
+
if (persona === void 0) return;
|
|
3464
|
+
updateRoleRow(index, { persona });
|
|
3465
|
+
});
|
|
3466
|
+
},
|
|
3467
|
+
children: t("roles.revertPersona")
|
|
3468
|
+
})]
|
|
3469
|
+
})
|
|
3470
|
+
]
|
|
3471
|
+
})
|
|
2470
3472
|
}),
|
|
2471
3473
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2472
|
-
className: FallbacksCard_module_css_default.
|
|
2473
|
-
children: [
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
3474
|
+
className: FallbacksCard_module_css_default.chainSelectors,
|
|
3475
|
+
children: [row.selectors.map((selector, selectorIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChainSelectorEditor, {
|
|
3476
|
+
selector,
|
|
3477
|
+
catalog: catalogOf(state),
|
|
3478
|
+
configuredProviders: state.configuredProviders,
|
|
3479
|
+
disabled: !writable,
|
|
3480
|
+
t,
|
|
3481
|
+
onChange: (patch) => {
|
|
3482
|
+
updateRoleSelector(index, selectorIndex, patch);
|
|
3483
|
+
},
|
|
3484
|
+
onRemove: () => {
|
|
3485
|
+
removeRoleSelector(index, selectorIndex);
|
|
3486
|
+
}
|
|
3487
|
+
}, selectorIndex)), row.selectors.every((selector) => selectorRowToRaw(selector) === "") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3488
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3489
|
+
children: seed !== void 0 ? t("roles.seedChainOptional", { id: row.id }) : t("validation.roleChainRequired", { id: row.id })
|
|
3490
|
+
})]
|
|
3491
|
+
}),
|
|
3492
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3493
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3494
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3495
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3496
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3497
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3498
|
+
children: t("roles.fallback")
|
|
3499
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3500
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3501
|
+
value: row.fallback,
|
|
3502
|
+
"aria-label": t("roles.fallback"),
|
|
2501
3503
|
disabled: !writable,
|
|
2502
3504
|
onChange: (event) => {
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
3505
|
+
updateRoleRow(index, { fallback: event.target.value });
|
|
3506
|
+
},
|
|
3507
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3508
|
+
value: "inherit-root",
|
|
3509
|
+
children: t("roles.fallback.inherit-root")
|
|
3510
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3511
|
+
value: "none",
|
|
3512
|
+
children: t("roles.fallback.none")
|
|
3513
|
+
})]
|
|
3514
|
+
})]
|
|
3515
|
+
})
|
|
3516
|
+
}),
|
|
3517
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3518
|
+
variant: "outline",
|
|
3519
|
+
size: "sm",
|
|
3520
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3521
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3522
|
+
onClick: () => {
|
|
3523
|
+
addRoleSelector(index);
|
|
3524
|
+
},
|
|
3525
|
+
children: t("roles.selector.add")
|
|
2513
3526
|
}),
|
|
3527
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3528
|
+
className: FallbacksCard_module_css_default.cardFoot,
|
|
3529
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3530
|
+
type: "button",
|
|
3531
|
+
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
3532
|
+
"data-tip": t("roles.remove"),
|
|
3533
|
+
"aria-label": t("roles.remove"),
|
|
3534
|
+
onClick: () => {
|
|
3535
|
+
removeRole(index);
|
|
3536
|
+
},
|
|
3537
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
3538
|
+
})
|
|
3539
|
+
})
|
|
3540
|
+
] })]
|
|
3541
|
+
}, index);
|
|
3542
|
+
})
|
|
3543
|
+
}),
|
|
3544
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3545
|
+
variant: "outline",
|
|
3546
|
+
size: "sm",
|
|
3547
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3548
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3549
|
+
onClick: addRole,
|
|
3550
|
+
children: t("roles.add")
|
|
3551
|
+
})
|
|
3552
|
+
]
|
|
3553
|
+
}),
|
|
3554
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3555
|
+
className: FallbacksCard_module_css_default.field,
|
|
3556
|
+
role: "group",
|
|
3557
|
+
"aria-labelledby": "fallbacks-roles-rules",
|
|
3558
|
+
children: [
|
|
3559
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3560
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3561
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3562
|
+
id: "fallbacks-roles-rules",
|
|
3563
|
+
children: t("roles.rules")
|
|
3564
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3565
|
+
label: t("roles.rules.tooltip"),
|
|
3566
|
+
disabled: !writable
|
|
3567
|
+
})]
|
|
3568
|
+
}),
|
|
3569
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3570
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3571
|
+
children: t("roles.rules.hint")
|
|
3572
|
+
}),
|
|
3573
|
+
state.catalogStatus === "error" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3574
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3575
|
+
children: t("catalog.error", { message: state.catalogError })
|
|
3576
|
+
}),
|
|
3577
|
+
state.catalogStatus === "ready" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3578
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3579
|
+
children: t("catalog.partial", { message: state.catalogError })
|
|
3580
|
+
}),
|
|
3581
|
+
state.catalogStatus === "ready" && (state.groups.length === 0 || state.configuredProviders.length === 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3582
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3583
|
+
children: t("catalog.empty")
|
|
3584
|
+
}),
|
|
3585
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3586
|
+
className: FallbacksCard_module_css_default.list,
|
|
3587
|
+
children: ruleRows.map((row, index) => {
|
|
3588
|
+
const catalog = catalogOf(state);
|
|
3589
|
+
const providerRaw = selectionToRaw(row.provider);
|
|
3590
|
+
const group = catalog?.groups.find((entry) => entry.id === providerRaw);
|
|
3591
|
+
const providerOutside = row.provider?.kind === "outside";
|
|
3592
|
+
const providerUnconfigured = !providerOutside && providerRaw !== "" && (catalog?.providers.some((entry) => entry.provider === providerRaw) ?? false) && !state.configuredProviders.some((entry) => entry.provider === providerRaw);
|
|
3593
|
+
const modelOutside = row.model?.kind === "outside";
|
|
3594
|
+
const roleOutside = row.role !== "" && !roleOptions.includes(row.role);
|
|
3595
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3596
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3597
|
+
children: [
|
|
2514
3598
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2515
|
-
className: FallbacksCard_module_css_default.
|
|
3599
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
2516
3600
|
children: [
|
|
2517
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
2518
|
-
className: FallbacksCard_module_css_default.
|
|
2519
|
-
children: [
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
3601
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3602
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3603
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3604
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3605
|
+
children: t("roles.rule.provider")
|
|
3606
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3607
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3608
|
+
value: providerRaw,
|
|
3609
|
+
onChange: (event) => {
|
|
3610
|
+
if (event.target.value === providerRaw) return;
|
|
3611
|
+
updateRuleRow(index, {
|
|
3612
|
+
provider: classifyProvider(event.target.value, catalog),
|
|
3613
|
+
model: null
|
|
3614
|
+
});
|
|
3615
|
+
},
|
|
3616
|
+
children: [
|
|
3617
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3618
|
+
value: "",
|
|
3619
|
+
children: t("roles.rule.provider.any")
|
|
3620
|
+
}),
|
|
3621
|
+
state.configuredProviders.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3622
|
+
value: entry.provider,
|
|
3623
|
+
children: entry.displayName
|
|
3624
|
+
}, entry.provider)),
|
|
3625
|
+
providerUnconfigured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3626
|
+
value: providerRaw,
|
|
3627
|
+
children: `${providerRaw}${t("catalog.unconfigured.short")}`
|
|
3628
|
+
}),
|
|
3629
|
+
providerOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3630
|
+
value: providerRaw,
|
|
3631
|
+
children: `${providerRaw}${t("catalog.outside.short")}`
|
|
3632
|
+
})
|
|
3633
|
+
]
|
|
3634
|
+
})]
|
|
2537
3635
|
}),
|
|
2538
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
}
|
|
2549
|
-
|
|
3636
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3637
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3638
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3639
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3640
|
+
children: t("roles.rule.model")
|
|
3641
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3642
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3643
|
+
value: selectionToRaw(row.model),
|
|
3644
|
+
onChange: (event) => {
|
|
3645
|
+
updateRuleRow(index, { model: classifyModel(providerRaw, event.target.value, catalog) });
|
|
3646
|
+
},
|
|
3647
|
+
children: [
|
|
3648
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3649
|
+
value: "",
|
|
3650
|
+
children: t("roles.rule.model.any")
|
|
3651
|
+
}),
|
|
3652
|
+
(group?.models ?? []).map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3653
|
+
value: model.id,
|
|
3654
|
+
children: model.name
|
|
3655
|
+
}, model.id)),
|
|
3656
|
+
modelOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3657
|
+
value: selectionToRaw(row.model),
|
|
3658
|
+
children: `${selectionToRaw(row.model)}${t("catalog.outside.short")}`
|
|
3659
|
+
})
|
|
3660
|
+
]
|
|
3661
|
+
})]
|
|
2550
3662
|
}),
|
|
2551
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2552
|
-
className: FallbacksCard_module_css_default.
|
|
2553
|
-
children:
|
|
3663
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3664
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3665
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3666
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3667
|
+
children: t("roles.rule.role")
|
|
3668
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3669
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3670
|
+
value: row.role,
|
|
3671
|
+
disabled: !writable,
|
|
3672
|
+
onChange: (event) => {
|
|
3673
|
+
updateRuleRow(index, { role: event.target.value });
|
|
3674
|
+
},
|
|
3675
|
+
children: [
|
|
3676
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3677
|
+
value: "",
|
|
3678
|
+
children: t("roles.rule.roleSelectPlaceholder")
|
|
3679
|
+
}),
|
|
3680
|
+
roleOptions.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3681
|
+
value: id,
|
|
3682
|
+
children: id === "inherit" ? t("roles.rule.role.inherit") : id
|
|
3683
|
+
}, id)),
|
|
3684
|
+
roleOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3685
|
+
value: row.role,
|
|
3686
|
+
children: `${row.role}${t("roles.rule.roleUndeclared.short")}`
|
|
3687
|
+
})
|
|
3688
|
+
]
|
|
3689
|
+
})]
|
|
2554
3690
|
})
|
|
2555
3691
|
]
|
|
3692
|
+
}),
|
|
3693
|
+
(providerOutside || modelOutside) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3694
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3695
|
+
children: [t("catalog.outside.hint"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3696
|
+
label: t("catalog.outside.tooltip"),
|
|
3697
|
+
disabled: !writable
|
|
3698
|
+
})]
|
|
3699
|
+
}),
|
|
3700
|
+
row.role === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3701
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3702
|
+
children: t("validation.ruleRoleRequired")
|
|
3703
|
+
}),
|
|
3704
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3705
|
+
className: FallbacksCard_module_css_default.cardFoot,
|
|
3706
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3707
|
+
type: "button",
|
|
3708
|
+
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
3709
|
+
"data-tip": t("roles.removeRule"),
|
|
3710
|
+
"aria-label": t("roles.removeRule"),
|
|
3711
|
+
onClick: () => {
|
|
3712
|
+
setRuleRows((rows) => rows.filter((_, rowIndex) => rowIndex !== index));
|
|
3713
|
+
},
|
|
3714
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
3715
|
+
})
|
|
2556
3716
|
})
|
|
2557
3717
|
]
|
|
2558
|
-
})
|
|
2559
|
-
|
|
2560
|
-
})
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
3718
|
+
}, index);
|
|
3719
|
+
})
|
|
3720
|
+
}),
|
|
3721
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3722
|
+
variant: "outline",
|
|
3723
|
+
size: "sm",
|
|
3724
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3725
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3726
|
+
onClick: () => {
|
|
3727
|
+
setRuleRows((rows) => [...rows, {
|
|
3728
|
+
provider: null,
|
|
3729
|
+
model: null,
|
|
3730
|
+
role: ""
|
|
3731
|
+
}]);
|
|
3732
|
+
},
|
|
3733
|
+
children: t("roles.addRule")
|
|
3734
|
+
})
|
|
3735
|
+
]
|
|
3736
|
+
}),
|
|
3737
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3738
|
+
className: FallbacksCard_module_css_default.field,
|
|
3739
|
+
role: "group",
|
|
3740
|
+
"aria-labelledby": "fallbacks-advanced",
|
|
3741
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3742
|
+
type: "button",
|
|
3743
|
+
className: FallbacksCard_module_css_default.sectionToggle,
|
|
3744
|
+
disabled: !writable,
|
|
3745
|
+
"aria-expanded": advancedVisible,
|
|
3746
|
+
"aria-controls": advancedVisible ? "fallbacks-advanced-body" : void 0,
|
|
3747
|
+
"aria-label": t(advancedVisible ? "advanced.collapse" : "advanced.expand"),
|
|
3748
|
+
onClick: () => {
|
|
3749
|
+
if (writable) setAdvancedOpen(!advancedOpen);
|
|
3750
|
+
},
|
|
3751
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3752
|
+
id: "fallbacks-advanced",
|
|
3753
|
+
className: FallbacksCard_module_css_default.sectionToggleText,
|
|
3754
|
+
children: t("advanced.label")
|
|
3755
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: advancedVisible ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron })]
|
|
3756
|
+
}), advancedVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3757
|
+
id: "fallbacks-advanced-body",
|
|
3758
|
+
children: [
|
|
3759
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3760
|
+
className: FallbacksCard_module_css_default.checkboxRow,
|
|
3761
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3762
|
+
className: FallbacksCard_module_css_default.checkLabel,
|
|
3763
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3764
|
+
className: FallbacksCard_module_css_default.checkLabelTitle,
|
|
3765
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3766
|
+
htmlFor: "fallbacks-role-automatch",
|
|
3767
|
+
children: t("roleAutoMatch.label")
|
|
3768
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3769
|
+
label: t("roleAutoMatch.tooltip"),
|
|
3770
|
+
disabled: !writable
|
|
3771
|
+
})]
|
|
3772
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3773
|
+
className: FallbacksCard_module_css_default.checkLabelDesc,
|
|
3774
|
+
children: t("roleAutoMatch.hint")
|
|
3775
|
+
})]
|
|
3776
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3777
|
+
id: "fallbacks-role-automatch",
|
|
3778
|
+
type: "checkbox",
|
|
3779
|
+
className: FallbacksCard_module_css_default.checkbox,
|
|
3780
|
+
checked: scalars.roleAutoMatch,
|
|
3781
|
+
disabled: !writable,
|
|
3782
|
+
onChange: (event) => {
|
|
3783
|
+
updateScalars((draft) => {
|
|
3784
|
+
draft.roleAutoMatch = event.target.checked;
|
|
3785
|
+
});
|
|
3786
|
+
}
|
|
3787
|
+
})]
|
|
3788
|
+
}),
|
|
3789
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3790
|
+
className: FallbacksCard_module_css_default.field,
|
|
3791
|
+
role: "group",
|
|
3792
|
+
"aria-labelledby": "fallbacks-trigger-codes",
|
|
3793
|
+
children: [
|
|
3794
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3795
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3796
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3797
|
+
id: "fallbacks-trigger-codes",
|
|
3798
|
+
children: t("triggerCodes.label")
|
|
3799
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3800
|
+
label: t("triggerCodes.tooltip"),
|
|
3801
|
+
disabled: !writable
|
|
3802
|
+
})]
|
|
3803
|
+
}),
|
|
3804
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3805
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3806
|
+
children: t("triggerCodes.hint")
|
|
3807
|
+
}),
|
|
3808
|
+
KNOWN_TRIGGER_CODES.map((code) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3809
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3810
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3811
|
+
type: "checkbox",
|
|
3812
|
+
checked: scalars.triggerCodes.includes(code),
|
|
3813
|
+
onChange: (event) => {
|
|
3814
|
+
updateScalars((draft) => {
|
|
3815
|
+
draft.triggerCodes = withTriggerCode(draft.triggerCodes, code, event.target.checked);
|
|
3816
|
+
});
|
|
3817
|
+
}
|
|
3818
|
+
}), t(TRIGGER_CODE_LABELS[code])]
|
|
3819
|
+
}, code)),
|
|
3820
|
+
unknownCodes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3821
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3822
|
+
children: t("triggerCodes.extra", { codes: unknownCodes.join(", ") })
|
|
3823
|
+
})
|
|
3824
|
+
]
|
|
3825
|
+
}),
|
|
3826
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3827
|
+
className: FallbacksCard_module_css_default.field,
|
|
3828
|
+
role: "group",
|
|
3829
|
+
"aria-labelledby": "fallbacks-revert-policy",
|
|
3830
|
+
children: [
|
|
3831
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3832
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3833
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3834
|
+
id: "fallbacks-revert-policy",
|
|
3835
|
+
children: t("revertPolicy.label")
|
|
3836
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3837
|
+
label: t("revertPolicy.tooltip"),
|
|
3838
|
+
disabled: !writable
|
|
3839
|
+
})]
|
|
3840
|
+
}),
|
|
3841
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3842
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3843
|
+
children: t("revertPolicy.hint")
|
|
3844
|
+
}),
|
|
3845
|
+
["cooldown-expiry", "never"].map((policy) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3846
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3847
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3848
|
+
type: "radio",
|
|
3849
|
+
name: "fallbacks-revert-policy",
|
|
3850
|
+
checked: scalars.revertPolicy === policy,
|
|
3851
|
+
onChange: () => {
|
|
3852
|
+
updateScalars((draft) => {
|
|
3853
|
+
draft.revertPolicy = policy;
|
|
3854
|
+
});
|
|
3855
|
+
}
|
|
3856
|
+
}), t(`revertPolicy.${policy}`)]
|
|
3857
|
+
}, policy))
|
|
3858
|
+
]
|
|
3859
|
+
}),
|
|
3860
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3861
|
+
className: FallbacksCard_module_css_default.numberFields,
|
|
3862
|
+
children: [
|
|
3863
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3864
|
+
className: FallbacksCard_module_css_default.field,
|
|
3865
|
+
children: [
|
|
3866
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3867
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3868
|
+
children: [
|
|
3869
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3870
|
+
htmlFor: "fallbacks-cooldown-ms",
|
|
3871
|
+
children: t("cooldownMs.label")
|
|
3872
|
+
}),
|
|
3873
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3874
|
+
label: t("cooldownMs.tooltip"),
|
|
3875
|
+
disabled: !writable
|
|
3876
|
+
}),
|
|
3877
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3878
|
+
className: FallbacksCard_module_css_default.defaultNote,
|
|
3879
|
+
children: [
|
|
3880
|
+
t("defaults.prefix"),
|
|
3881
|
+
": ",
|
|
3882
|
+
state.config.cooldownMs
|
|
3883
|
+
]
|
|
3884
|
+
})
|
|
3885
|
+
]
|
|
3886
|
+
}),
|
|
3887
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3888
|
+
id: "fallbacks-cooldown-ms",
|
|
3889
|
+
className: FallbacksCard_module_css_default.input,
|
|
3890
|
+
type: "number",
|
|
3891
|
+
min: 0,
|
|
3892
|
+
value: String(scalars.cooldownMs),
|
|
3893
|
+
disabled: !writable,
|
|
3894
|
+
onChange: (event) => {
|
|
3895
|
+
updateScalars((draft) => {
|
|
3896
|
+
draft.cooldownMs = parseCount(event.target.value);
|
|
3897
|
+
});
|
|
3898
|
+
}
|
|
3899
|
+
}),
|
|
3900
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3901
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3902
|
+
children: t("cooldownMs.hint")
|
|
3903
|
+
})
|
|
3904
|
+
]
|
|
3905
|
+
}),
|
|
3906
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3907
|
+
className: FallbacksCard_module_css_default.field,
|
|
3908
|
+
children: [
|
|
3909
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3910
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3911
|
+
children: [
|
|
3912
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3913
|
+
htmlFor: "fallbacks-max-switches",
|
|
3914
|
+
children: t("maxSwitchesPerStep.label")
|
|
3915
|
+
}),
|
|
3916
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3917
|
+
label: t("maxSwitchesPerStep.tooltip"),
|
|
3918
|
+
disabled: !writable
|
|
3919
|
+
}),
|
|
3920
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3921
|
+
className: FallbacksCard_module_css_default.defaultNote,
|
|
3922
|
+
children: [
|
|
3923
|
+
t("defaults.prefix"),
|
|
3924
|
+
": ",
|
|
3925
|
+
state.config.maxSwitchesPerStep
|
|
3926
|
+
]
|
|
3927
|
+
})
|
|
3928
|
+
]
|
|
3929
|
+
}),
|
|
3930
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3931
|
+
id: "fallbacks-max-switches",
|
|
3932
|
+
className: FallbacksCard_module_css_default.input,
|
|
3933
|
+
type: "number",
|
|
3934
|
+
min: 0,
|
|
3935
|
+
value: String(scalars.maxSwitchesPerStep),
|
|
3936
|
+
disabled: !writable,
|
|
3937
|
+
onChange: (event) => {
|
|
3938
|
+
updateScalars((draft) => {
|
|
3939
|
+
draft.maxSwitchesPerStep = parseCount(event.target.value);
|
|
3940
|
+
});
|
|
3941
|
+
}
|
|
3942
|
+
}),
|
|
3943
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3944
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3945
|
+
children: t("maxSwitchesPerStep.hint")
|
|
3946
|
+
})
|
|
3947
|
+
]
|
|
3948
|
+
}),
|
|
3949
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3950
|
+
className: FallbacksCard_module_css_default.field,
|
|
3951
|
+
children: [
|
|
3952
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3953
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3954
|
+
children: [
|
|
3955
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3956
|
+
htmlFor: "fallbacks-always-cap",
|
|
3957
|
+
children: t("alwaysModeRetryCap.label")
|
|
3958
|
+
}),
|
|
3959
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3960
|
+
label: t("alwaysModeRetryCap.tooltip"),
|
|
3961
|
+
disabled: !writable
|
|
3962
|
+
}),
|
|
3963
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3964
|
+
className: FallbacksCard_module_css_default.defaultNote,
|
|
3965
|
+
children: [
|
|
3966
|
+
t("defaults.prefix"),
|
|
3967
|
+
": ",
|
|
3968
|
+
state.config.alwaysModeRetryCap
|
|
3969
|
+
]
|
|
3970
|
+
})
|
|
3971
|
+
]
|
|
3972
|
+
}),
|
|
3973
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3974
|
+
id: "fallbacks-always-cap",
|
|
3975
|
+
className: FallbacksCard_module_css_default.input,
|
|
3976
|
+
type: "number",
|
|
3977
|
+
min: 0,
|
|
3978
|
+
value: String(scalars.alwaysModeRetryCap),
|
|
3979
|
+
disabled: !writable,
|
|
3980
|
+
onChange: (event) => {
|
|
3981
|
+
updateScalars((draft) => {
|
|
3982
|
+
draft.alwaysModeRetryCap = parseCount(event.target.value);
|
|
3983
|
+
});
|
|
3984
|
+
}
|
|
3985
|
+
}),
|
|
3986
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3987
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3988
|
+
children: t("alwaysModeRetryCap.hint")
|
|
3989
|
+
})
|
|
3990
|
+
]
|
|
3991
|
+
})
|
|
3992
|
+
]
|
|
3993
|
+
}),
|
|
3994
|
+
validationErrors.advanced.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3995
|
+
className: FallbacksCard_module_css_default.error,
|
|
3996
|
+
role: "alert",
|
|
3997
|
+
children: `${t("validation.blocked")}${validationErrors.advanced.join("; ")}`
|
|
3998
|
+
}),
|
|
3999
|
+
lastSaveSection === "advanced" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4000
|
+
className: FallbacksCard_module_css_default.error,
|
|
4001
|
+
role: "alert",
|
|
4002
|
+
children: t("error.generic", { message: state.error })
|
|
4003
|
+
}),
|
|
4004
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4005
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
4006
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4007
|
+
type: "button",
|
|
4008
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
4009
|
+
disabled: !advancedDirty || saving,
|
|
4010
|
+
onClick: () => {
|
|
4011
|
+
discardSection("advanced");
|
|
4012
|
+
},
|
|
4013
|
+
children: t("discard")
|
|
4014
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4015
|
+
type: "button",
|
|
4016
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
4017
|
+
disabled: !writable || saving || !advancedDirty,
|
|
4018
|
+
onClick: () => {
|
|
4019
|
+
save("advanced");
|
|
4020
|
+
},
|
|
4021
|
+
children: saving ? t("save.saving") : t("save")
|
|
4022
|
+
})]
|
|
4023
|
+
})
|
|
4024
|
+
]
|
|
4025
|
+
})]
|
|
4026
|
+
})
|
|
4027
|
+
]
|
|
4028
|
+
})
|
|
4029
|
+
]
|
|
4030
|
+
}),
|
|
4031
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4032
|
+
className: FallbacksCard_module_css_default.statusBlock,
|
|
4033
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4034
|
+
className: FallbacksCard_module_css_default.statusTitle,
|
|
4035
|
+
children: t("status.title")
|
|
4036
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
4037
|
+
className: FallbacksCard_module_css_default.statusLine,
|
|
4038
|
+
role: state.switchesStatus === "error" ? "alert" : void 0,
|
|
2568
4039
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2569
|
-
className: FallbacksCard_module_css_default.
|
|
2570
|
-
children: t("status.
|
|
2571
|
-
}),
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
children: t("status.switches.label")
|
|
2577
|
-
}), switchesLine]
|
|
2578
|
-
})]
|
|
2579
|
-
}),
|
|
2580
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2581
|
-
className: FallbacksCard_module_css_default.footer,
|
|
2582
|
-
children: [
|
|
2583
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2584
|
-
type: "button",
|
|
2585
|
-
className: FallbacksCard_module_css_default.secondaryButton,
|
|
2586
|
-
disabled: !dirty || saving,
|
|
2587
|
-
onClick: discard,
|
|
2588
|
-
children: t("discard")
|
|
2589
|
-
}),
|
|
2590
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2591
|
-
type: "button",
|
|
2592
|
-
className: FallbacksCard_module_css_default.secondaryButton,
|
|
2593
|
-
disabled: !writable || saving,
|
|
2594
|
-
onClick: () => {
|
|
2595
|
-
setConfirmingReset(true);
|
|
2596
|
-
},
|
|
2597
|
-
children: t("reset")
|
|
2598
|
-
}),
|
|
2599
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2600
|
-
type: "button",
|
|
2601
|
-
className: FallbacksCard_module_css_default.primaryButton,
|
|
2602
|
-
disabled: !writable || saving || !dirty,
|
|
2603
|
-
onClick: save,
|
|
2604
|
-
children: saving ? t("save.saving") : t("save")
|
|
2605
|
-
})
|
|
2606
|
-
]
|
|
2607
|
-
})
|
|
2608
|
-
]
|
|
2609
|
-
}),
|
|
2610
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2611
|
-
open: confirmingReset,
|
|
2612
|
-
onClose: () => {
|
|
2613
|
-
if (!resetting) setConfirmingReset(false);
|
|
2614
|
-
},
|
|
2615
|
-
title: t("reset.confirmTitle"),
|
|
2616
|
-
closeLabel: t("close"),
|
|
2617
|
-
description: t("reset.confirm"),
|
|
2618
|
-
className: FallbacksCard_module_css_default.resetDialog,
|
|
2619
|
-
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2620
|
-
variant: "outline",
|
|
2621
|
-
autoFocus: true,
|
|
2622
|
-
disabled: resetting,
|
|
2623
|
-
onClick: () => {
|
|
2624
|
-
setConfirmingReset(false);
|
|
2625
|
-
},
|
|
2626
|
-
children: t("reset.confirm.cancel")
|
|
2627
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2628
|
-
variant: "outline",
|
|
2629
|
-
className: FallbacksCard_module_css_default.confirmDanger,
|
|
2630
|
-
disabled: resetting,
|
|
2631
|
-
onClick: confirmReset,
|
|
2632
|
-
children: resetting ? t("reset.saving") : t("reset.confirm.action")
|
|
2633
|
-
})] })
|
|
2634
|
-
})
|
|
2635
|
-
]
|
|
4040
|
+
className: FallbacksCard_module_css_default.statusLineLabel,
|
|
4041
|
+
children: t("status.switches.label")
|
|
4042
|
+
}), switchesLine]
|
|
4043
|
+
})]
|
|
4044
|
+
})
|
|
4045
|
+
]
|
|
4046
|
+
})]
|
|
2636
4047
|
});
|
|
2637
4048
|
}
|
|
2638
4049
|
//#endregion
|
|
@@ -2935,7 +4346,7 @@ window.__ModuleLoader__.load({
|
|
|
2935
4346
|
const connection = ctx.get("connection");
|
|
2936
4347
|
const sessions = ctx.get("sessions");
|
|
2937
4348
|
const controller = new FallbacksSettingsController(connection.api, connection.rpc);
|
|
2938
|
-
const useSnapshot =
|
|
4349
|
+
const useSnapshot = bindSnapshotSelector(controller.store);
|
|
2939
4350
|
ctx.effect(() => {
|
|
2940
4351
|
const syncSession = () => {
|
|
2941
4352
|
controller.setCurrentSession(sessions?.list.getSnapshot().current);
|