dsh-llm-fallbacks 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -7
- package/README.zh-CN.md +65 -7
- package/dist/client/FallbacksCard.d.ts +26 -12
- package/dist/client/fallbacks-store.d.ts +48 -4
- package/dist/client/index.js +2187 -935
- package/dist/client/locales.d.ts +118 -26
- 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 +1 -1
package/dist/client/index.js
CHANGED
|
@@ -38,6 +38,238 @@ window.__ModuleLoader__.load({
|
|
|
38
38
|
raw: trimmed
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Frozen preset windows (UTC+8). `liang-*` presets have NO day mask (they
|
|
43
|
+
* apply every day, weekends included); `glm-peak` is Monday–Friday only.
|
|
44
|
+
* The two valleys are `complement: true` of their peak.
|
|
45
|
+
*/
|
|
46
|
+
const PRESETS = {
|
|
47
|
+
"liang-peak": {
|
|
48
|
+
windows: [{
|
|
49
|
+
start: "09:00",
|
|
50
|
+
end: "12:00"
|
|
51
|
+
}, {
|
|
52
|
+
start: "14:00",
|
|
53
|
+
end: "18:00"
|
|
54
|
+
}],
|
|
55
|
+
complement: false,
|
|
56
|
+
label: "Liang Peak"
|
|
57
|
+
},
|
|
58
|
+
"liang-valley": {
|
|
59
|
+
windows: [{
|
|
60
|
+
start: "09:00",
|
|
61
|
+
end: "12:00"
|
|
62
|
+
}, {
|
|
63
|
+
start: "14:00",
|
|
64
|
+
end: "18:00"
|
|
65
|
+
}],
|
|
66
|
+
complement: true,
|
|
67
|
+
label: "Liang Valley"
|
|
68
|
+
},
|
|
69
|
+
"glm-peak": {
|
|
70
|
+
windows: [{
|
|
71
|
+
start: "14:00",
|
|
72
|
+
end: "18:00",
|
|
73
|
+
days: [
|
|
74
|
+
1,
|
|
75
|
+
2,
|
|
76
|
+
3,
|
|
77
|
+
4,
|
|
78
|
+
5
|
|
79
|
+
]
|
|
80
|
+
}],
|
|
81
|
+
complement: false,
|
|
82
|
+
label: "GLM Peak"
|
|
83
|
+
},
|
|
84
|
+
"glm-valley": {
|
|
85
|
+
windows: [{
|
|
86
|
+
start: "14:00",
|
|
87
|
+
end: "18:00",
|
|
88
|
+
days: [
|
|
89
|
+
1,
|
|
90
|
+
2,
|
|
91
|
+
3,
|
|
92
|
+
4,
|
|
93
|
+
5
|
|
94
|
+
]
|
|
95
|
+
}],
|
|
96
|
+
complement: true,
|
|
97
|
+
label: "GLM Valley"
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const HHMM_RE$1 = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
101
|
+
const WEEKDAY_INDEX = {
|
|
102
|
+
Sun: 0,
|
|
103
|
+
Mon: 1,
|
|
104
|
+
Tue: 2,
|
|
105
|
+
Wed: 3,
|
|
106
|
+
Thu: 4,
|
|
107
|
+
Fri: 5,
|
|
108
|
+
Sat: 6
|
|
109
|
+
};
|
|
110
|
+
/** Malformed rows warn once per row INSTANCE (config snapshots are stable
|
|
111
|
+
* across requests — this is what keeps "warn once" from becoming spam). */
|
|
112
|
+
const warnedMalformedRows = /* @__PURE__ */ new WeakSet();
|
|
113
|
+
/** Invalid `tz` values warn once per distinct value. */
|
|
114
|
+
const warnedTimeZones = /* @__PURE__ */ new Set();
|
|
115
|
+
function warnMalformed(row, reason) {
|
|
116
|
+
if (typeof row !== "object" || row === null) {
|
|
117
|
+
console.warn(`llm-fallbacks: skipping malformed time-slot row (${reason})`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (warnedMalformedRows.has(row)) return;
|
|
121
|
+
warnedMalformedRows.add(row);
|
|
122
|
+
console.warn(`llm-fallbacks: skipping malformed time-slot row (${reason}): ${JSON.stringify(row)}`);
|
|
123
|
+
}
|
|
124
|
+
/** Wall-clock weekday (0=Sunday) + minutes-since-midnight of `now` in `tz`
|
|
125
|
+
* (standard `Intl` timezone rules, DST-safe). */
|
|
126
|
+
function wallClock(now, tz) {
|
|
127
|
+
try {
|
|
128
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
129
|
+
timeZone: tz,
|
|
130
|
+
weekday: "short",
|
|
131
|
+
hour: "2-digit",
|
|
132
|
+
minute: "2-digit",
|
|
133
|
+
hourCycle: "h23"
|
|
134
|
+
}).formatToParts(now);
|
|
135
|
+
let weekday = 0;
|
|
136
|
+
let minutes = 0;
|
|
137
|
+
for (const part of parts) if (part.type === "weekday") weekday = WEEKDAY_INDEX[part.value] ?? 0;
|
|
138
|
+
else if (part.type === "hour") minutes += Number(part.value) * 60;
|
|
139
|
+
else if (part.type === "minute") minutes += Number(part.value);
|
|
140
|
+
return {
|
|
141
|
+
weekday,
|
|
142
|
+
minutes
|
|
143
|
+
};
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (!warnedTimeZones.has(tz)) {
|
|
146
|
+
warnedTimeZones.add(tz);
|
|
147
|
+
console.warn(`llm-fallbacks: invalid timezone "${tz}" (${error.message}) — slot matching falls back to UTC`);
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
weekday: now.getUTCDay(),
|
|
151
|
+
minutes: now.getUTCHours() * 60 + now.getUTCMinutes()
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** `HH:mm` → minutes-since-midnight (inputs are regex-validated or frozen
|
|
156
|
+
* constants — this never sees garbage). */
|
|
157
|
+
function minutesOf(hhmm) {
|
|
158
|
+
const [hour, minute] = hhmm.split(":").map(Number);
|
|
159
|
+
return hour * 60 + minute;
|
|
160
|
+
}
|
|
161
|
+
/** P4 containment rule: day mask matches AND the window contains `t`
|
|
162
|
+
* (`end` exclusive; `start > end` wraps midnight — custom rows only). */
|
|
163
|
+
function containsWindow(window, clock) {
|
|
164
|
+
if (!(window.days === void 0 || window.days.length === 0 || window.days.includes(clock.weekday))) return false;
|
|
165
|
+
const start = minutesOf(window.start);
|
|
166
|
+
const end = minutesOf(window.end);
|
|
167
|
+
return start <= end ? start <= clock.minutes && clock.minutes < end : start <= clock.minutes || clock.minutes < end;
|
|
168
|
+
}
|
|
169
|
+
function matchesAnyWindow(windows, clock) {
|
|
170
|
+
return windows.some((window) => containsWindow(window, clock));
|
|
171
|
+
}
|
|
172
|
+
/** Validate one stored row → frozen windows, or `undefined` (warn once +
|
|
173
|
+
* skip). Preset rows reject stored windows/day masks (P4); custom rows
|
|
174
|
+
* require strict `HH:mm` bounds; chains must be non-empty. */
|
|
175
|
+
function describeRow(row) {
|
|
176
|
+
if (!Array.isArray(row.chain) || row.chain.length === 0) {
|
|
177
|
+
warnMalformed(row, "empty chain");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (row.kind === "preset") {
|
|
181
|
+
const preset = row.preset;
|
|
182
|
+
if (typeof preset !== "string" || !Object.hasOwn(PRESETS, preset)) {
|
|
183
|
+
warnMalformed(row, `unknown preset ${JSON.stringify(preset)}`);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (row.start !== void 0 || row.end !== void 0 || row.days !== void 0 && row.days.length > 0) {
|
|
187
|
+
warnMalformed(row, `preset windows are fixed — row "${preset}" cannot carry start/end/days`);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
return PRESETS[preset];
|
|
191
|
+
}
|
|
192
|
+
if (row.kind === "custom") {
|
|
193
|
+
const { start, end } = row;
|
|
194
|
+
if (typeof start !== "string" || typeof end !== "string" || !HHMM_RE$1.test(start) || !HHMM_RE$1.test(end)) {
|
|
195
|
+
warnMalformed(row, `invalid custom window ${JSON.stringify(start)}-${JSON.stringify(end)} (expected HH:mm)`);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
windows: [{
|
|
200
|
+
start,
|
|
201
|
+
end,
|
|
202
|
+
days: row.days
|
|
203
|
+
}],
|
|
204
|
+
complement: false
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
warnMalformed(row, `unknown kind ${JSON.stringify(row.kind)}`);
|
|
208
|
+
}
|
|
209
|
+
/** Display label for a winning row (preset rows use the frozen label;
|
|
210
|
+
* custom rows prefer their display name, falling back to the window). */
|
|
211
|
+
function labelOf(row) {
|
|
212
|
+
if (row.kind === "preset" && typeof row.preset === "string" && Object.hasOwn(PRESETS, row.preset)) return PRESETS[row.preset].label;
|
|
213
|
+
return row.name !== void 0 && row.name.trim() !== "" ? row.name : `custom ${row.start}-${row.end}`;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* All-day conformance (P6): the all-day chain is conforming when its LAST
|
|
217
|
+
* entry (the tail — the card's 默认模型 panel) is exactly one official V4
|
|
218
|
+
* model — Flash XOR Pro. Leading entries (the card's 默认降级链 block) are
|
|
219
|
+
* the ordered walk before that last-resort fallback. An empty chain or a
|
|
220
|
+
* chain whose tail is not an official V4 model keeps slot rows inert and
|
|
221
|
+
* refuses the virtual-row override/delegate; the v0.2.2 failure walk over
|
|
222
|
+
* the raw chain stays verbatim.
|
|
223
|
+
*/
|
|
224
|
+
function isAllDayConforming(chain) {
|
|
225
|
+
if (chain.length < 1) return false;
|
|
226
|
+
const tail = chain[chain.length - 1];
|
|
227
|
+
return tail === "deepseek-official/deepseek-v4-flash" || tail === "deepseek-official/deepseek-v4-pro";
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Slot winner + display label (P5): drives 分时切换 detection (per-root-agent
|
|
231
|
+
* last-winner marker, in-process only) and the card / `/fallbacks` status
|
|
232
|
+
* strip. `winner` is the matching row or `'all-day'`; `label` names the
|
|
233
|
+
* slot (frozen preset label or `custom HH:mm-HH:mm`).
|
|
234
|
+
*
|
|
235
|
+
* P6 gate (qc1 F-001): without a conforming all-day
|
|
236
|
+
* (`isAllDayConforming(config.rootChain)`) the winner is ALWAYS `'all-day'`
|
|
237
|
+
* — a legacy multi-model (or empty) chain earns no slot rows, so every
|
|
238
|
+
* surface fed by this resolver reports the inert state and routing stays on
|
|
239
|
+
* the raw `rootChain` (the v0.2.2 walk verbatim).
|
|
240
|
+
*/
|
|
241
|
+
function resolveSlotState(config, now, tz) {
|
|
242
|
+
if (!isAllDayConforming(config.rootChain)) return {
|
|
243
|
+
winner: "all-day",
|
|
244
|
+
label: "all-day"
|
|
245
|
+
};
|
|
246
|
+
const clock = wallClock(now, tz);
|
|
247
|
+
const seenPresets = /* @__PURE__ */ new Set();
|
|
248
|
+
const rows = Array.isArray(config.timeSlots) ? config.timeSlots : [];
|
|
249
|
+
for (const row of rows) {
|
|
250
|
+
if (typeof row !== "object" || row === null) {
|
|
251
|
+
warnMalformed(row, "row is not an object");
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (row.kind === "preset" && typeof row.preset === "string") {
|
|
255
|
+
if (seenPresets.has(row.preset)) {
|
|
256
|
+
warnMalformed(row, `duplicate preset "${row.preset}" — only the first row takes effect`);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
seenPresets.add(row.preset);
|
|
260
|
+
}
|
|
261
|
+
const descriptor = describeRow(row);
|
|
262
|
+
if (descriptor === void 0) continue;
|
|
263
|
+
if (descriptor.complement ? !matchesAnyWindow(descriptor.windows, clock) : matchesAnyWindow(descriptor.windows, clock)) return {
|
|
264
|
+
winner: row,
|
|
265
|
+
label: labelOf(row)
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
winner: "all-day",
|
|
270
|
+
label: "all-day"
|
|
271
|
+
};
|
|
272
|
+
}
|
|
41
273
|
//#endregion
|
|
42
274
|
//#region src/config.ts
|
|
43
275
|
/**
|
|
@@ -64,7 +296,9 @@ window.__ModuleLoader__.load({
|
|
|
64
296
|
maxSwitchesPerStep: 8,
|
|
65
297
|
alwaysModeRetryCap: 5,
|
|
66
298
|
presets: "bundled",
|
|
67
|
-
roleAutoMatch: true
|
|
299
|
+
roleAutoMatch: true,
|
|
300
|
+
timeSlots: [],
|
|
301
|
+
tz: "Asia/Shanghai"
|
|
68
302
|
};
|
|
69
303
|
/**
|
|
70
304
|
* Reserved role id: legal as a rule target (`roles.rules[].role`) and as
|
|
@@ -115,6 +349,15 @@ window.__ModuleLoader__.load({
|
|
|
115
349
|
return typeof entry.id === "string" && typeof entry.overridden === "boolean";
|
|
116
350
|
});
|
|
117
351
|
}
|
|
352
|
+
/** Seed-default persona from a revert-seed wire body (issue #59). */
|
|
353
|
+
function revertOutcomePersona(value) {
|
|
354
|
+
if (value === null || typeof value !== "object" || !("outcome" in value)) return void 0;
|
|
355
|
+
const outcome = value.outcome;
|
|
356
|
+
if (outcome === null || typeof outcome !== "object") return void 0;
|
|
357
|
+
if (!("reverted" in outcome) || outcome.reverted !== true) return void 0;
|
|
358
|
+
if (!("persona" in outcome) || typeof outcome.persona !== "string") return void 0;
|
|
359
|
+
return outcome.persona;
|
|
360
|
+
}
|
|
118
361
|
/**
|
|
119
362
|
* The provider dropdown's offer set (spec §2.5 D-4): catalog providers whose
|
|
120
363
|
* settings profile resolves in the describe namespaces — the Models page's
|
|
@@ -195,6 +438,23 @@ window.__ModuleLoader__.load({
|
|
|
195
438
|
if (enabled !== void 0 && typeof enabled !== "boolean") throw new TypeError("fallbacks descriptor enabled must be a boolean");
|
|
196
439
|
const roleAutoMatch = value.roleAutoMatch;
|
|
197
440
|
if (roleAutoMatch !== void 0 && typeof roleAutoMatch !== "boolean") throw new TypeError("fallbacks descriptor roleAutoMatch must be a boolean");
|
|
441
|
+
const timeSlots = value.timeSlots;
|
|
442
|
+
if (timeSlots !== void 0 && (!Array.isArray(timeSlots) || timeSlots.some((row) => {
|
|
443
|
+
if (!isRecord(row)) return true;
|
|
444
|
+
for (const field of [
|
|
445
|
+
"kind",
|
|
446
|
+
"preset",
|
|
447
|
+
"start",
|
|
448
|
+
"end"
|
|
449
|
+
]) if (row[field] !== void 0 && typeof row[field] !== "string") return true;
|
|
450
|
+
const chain = row.chain;
|
|
451
|
+
if (chain !== void 0 && (!Array.isArray(chain) || chain.some((entry) => typeof entry !== "string"))) return true;
|
|
452
|
+
const days = row.days;
|
|
453
|
+
if (days !== void 0 && (!Array.isArray(days) || days.some((day) => typeof day !== "number"))) return true;
|
|
454
|
+
return false;
|
|
455
|
+
}))) throw new TypeError("fallbacks descriptor timeSlots must be an array of slot rows (kind/preset/start/end strings, chain string array, days number array)");
|
|
456
|
+
const tz = value.tz;
|
|
457
|
+
if (tz !== void 0 && typeof tz !== "string") throw new TypeError("fallbacks descriptor tz must be a string");
|
|
198
458
|
return {
|
|
199
459
|
enabled: enabled ?? defaultFallbacksConfig.enabled,
|
|
200
460
|
triggerCodes: triggerCodes ?? [...defaultFallbacksConfig.triggerCodes],
|
|
@@ -208,7 +468,9 @@ window.__ModuleLoader__.load({
|
|
|
208
468
|
maxSwitchesPerStep: maxSwitchesPerStep ?? defaultFallbacksConfig.maxSwitchesPerStep,
|
|
209
469
|
alwaysModeRetryCap: alwaysModeRetryCap ?? defaultFallbacksConfig.alwaysModeRetryCap,
|
|
210
470
|
presets: presets ?? defaultFallbacksConfig.presets,
|
|
211
|
-
roleAutoMatch: roleAutoMatch ?? defaultFallbacksConfig.roleAutoMatch
|
|
471
|
+
roleAutoMatch: roleAutoMatch ?? defaultFallbacksConfig.roleAutoMatch,
|
|
472
|
+
timeSlots: timeSlots ?? [...defaultFallbacksConfig.timeSlots ?? []],
|
|
473
|
+
tz: tz ?? defaultFallbacksConfig.tz
|
|
212
474
|
};
|
|
213
475
|
}
|
|
214
476
|
/** The raw selector string a selection serializes to ('' when empty). */
|
|
@@ -310,13 +572,54 @@ window.__ModuleLoader__.load({
|
|
|
310
572
|
}
|
|
311
573
|
return entries;
|
|
312
574
|
}
|
|
575
|
+
/** Project the time-slot rows into editable rows (chain selectors classified). */
|
|
576
|
+
function timeSlotsToRows(timeSlots, catalog) {
|
|
577
|
+
return timeSlots.map((row) => ({
|
|
578
|
+
kind: row.kind,
|
|
579
|
+
...row.preset === void 0 ? {} : { preset: row.preset },
|
|
580
|
+
start: row.start ?? "",
|
|
581
|
+
end: row.end ?? "",
|
|
582
|
+
days: [...row.days ?? []],
|
|
583
|
+
name: row.name ?? "",
|
|
584
|
+
collapsed: true,
|
|
585
|
+
selectors: (row.chain ?? []).map((entry) => entryToSelectorRow(entry, catalog))
|
|
586
|
+
}));
|
|
587
|
+
}
|
|
588
|
+
/** Rebuild the time-slot rows from edited rows; blank selectors drop out.
|
|
589
|
+
* `kind` rides verbatim (a hand-written unknown kind reads back unchanged;
|
|
590
|
+
* save validation rejects it) — the cast asserts the trusted editor shape.
|
|
591
|
+
* `days` is ALWAYS serialized ([] included): schemastery composes absent
|
|
592
|
+
* array fields as `[]`, so the composed config every card load accepts
|
|
593
|
+
* carries `days` on every row — the draft must too, or a clean card would
|
|
594
|
+
* read back dirty. */
|
|
595
|
+
function rowsToTimeSlots(rows) {
|
|
596
|
+
return rows.map((row) => {
|
|
597
|
+
const chain = row.selectors.map(selectorRowToRaw).filter((entry) => entry !== "");
|
|
598
|
+
if (row.kind === "preset") return {
|
|
599
|
+
kind: "preset",
|
|
600
|
+
preset: row.preset,
|
|
601
|
+
days: row.days,
|
|
602
|
+
chain
|
|
603
|
+
};
|
|
604
|
+
return {
|
|
605
|
+
kind: row.kind,
|
|
606
|
+
...row.preset === void 0 ? {} : { preset: row.preset },
|
|
607
|
+
start: row.start,
|
|
608
|
+
end: row.end,
|
|
609
|
+
days: row.days,
|
|
610
|
+
...row.name === "" ? {} : { name: row.name },
|
|
611
|
+
chain
|
|
612
|
+
};
|
|
613
|
+
});
|
|
614
|
+
}
|
|
313
615
|
/** Project the declared roles into editable rows (chain selectors classified). */
|
|
314
616
|
function rolesToRows(roles, catalog) {
|
|
315
617
|
return roles.map((role) => ({
|
|
316
618
|
id: role.id,
|
|
317
619
|
persona: role.persona,
|
|
318
620
|
selectors: (role.chain ?? []).map((entry) => entryToSelectorRow(entry, catalog)),
|
|
319
|
-
fallback: role.fallback ?? "inherit-root"
|
|
621
|
+
fallback: role.fallback ?? "inherit-root",
|
|
622
|
+
collapsed: true
|
|
320
623
|
}));
|
|
321
624
|
}
|
|
322
625
|
/** Rebuild the declared roles from edited rows; empty selectors drop out. */
|
|
@@ -365,16 +668,14 @@ window.__ModuleLoader__.load({
|
|
|
365
668
|
/** Project the role rules into editable rows (provider/model classified). */
|
|
366
669
|
function rulesToRows(rules, catalog) {
|
|
367
670
|
return rules.map((rule) => ({
|
|
368
|
-
origin: rule.origin ?? "",
|
|
369
671
|
provider: classifyProvider(rule.provider ?? "", catalog),
|
|
370
672
|
model: classifyModel(rule.provider ?? "", rule.model ?? "", catalog),
|
|
371
673
|
role: rule.role
|
|
372
674
|
}));
|
|
373
675
|
}
|
|
374
|
-
/** Rebuild the role rules from edited rows; empty
|
|
676
|
+
/** Rebuild the role rules from edited rows; empty provider/model drop out. */
|
|
375
677
|
function rowsToRules(rows) {
|
|
376
678
|
return rows.map((row) => ({
|
|
377
|
-
...row.origin === "" ? {} : { origin: row.origin },
|
|
378
679
|
...row.provider === null ? {} : { provider: selectionToRaw(row.provider) },
|
|
379
680
|
...row.model === null ? {} : { model: selectionToRaw(row.model) },
|
|
380
681
|
role: row.role.trim()
|
|
@@ -658,12 +959,17 @@ window.__ModuleLoader__.load({
|
|
|
658
959
|
* reason }` outcome is still a successful RPC — the post-write read
|
|
659
960
|
* result (config / legacyKeys / seeds) lands either way, and the revert
|
|
660
961
|
* button stays disabled while the write is in flight.
|
|
962
|
+
*
|
|
963
|
+
* Returns the seed-default persona when the outcome is `{ reverted:
|
|
964
|
+
* true, persona }` — including the persist no-op (persisted already
|
|
965
|
+
* equals the seed). The card applies that string to the row's **draft**
|
|
966
|
+
* so an unsaved persona edit still snaps back (issue #59).
|
|
661
967
|
* @param id - the seeded role id; the host matches it by trimmed id
|
|
662
968
|
* against the seed registry (spec §9.3).
|
|
663
969
|
*/
|
|
664
970
|
async revertSeed(id) {
|
|
665
971
|
const state = this.store.getSnapshot();
|
|
666
|
-
if (!state.writable || state.status === "saving") return;
|
|
972
|
+
if (!state.writable || state.status === "saving") return void 0;
|
|
667
973
|
const generation = ++this.writeGeneration;
|
|
668
974
|
this.store.update((draft) => {
|
|
669
975
|
draft.status = "saving";
|
|
@@ -671,7 +977,7 @@ window.__ModuleLoader__.load({
|
|
|
671
977
|
});
|
|
672
978
|
try {
|
|
673
979
|
const result = await this.rpc.call("/api", "fallbacks/revert-seed", { args: { id } });
|
|
674
|
-
if (generation !== this.writeGeneration) return;
|
|
980
|
+
if (generation !== this.writeGeneration) return void 0;
|
|
675
981
|
if (!result.ok) throw result.error;
|
|
676
982
|
const value = result.value;
|
|
677
983
|
const config = value !== null && typeof value === "object" && "config" in value ? value.config : void 0;
|
|
@@ -686,9 +992,11 @@ window.__ModuleLoader__.load({
|
|
|
686
992
|
if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
|
|
687
993
|
}
|
|
688
994
|
this.accept(config, true, legacyKeys, seeds);
|
|
995
|
+
return revertOutcomePersona(value);
|
|
689
996
|
} catch (error) {
|
|
690
|
-
if (generation !== this.writeGeneration) return;
|
|
997
|
+
if (generation !== this.writeGeneration) return void 0;
|
|
691
998
|
this.fail(error);
|
|
999
|
+
return;
|
|
692
1000
|
}
|
|
693
1001
|
}
|
|
694
1002
|
/** Stop in-flight responses from publishing after plugin disposal. */
|
|
@@ -817,16 +1125,62 @@ window.__ModuleLoader__.load({
|
|
|
817
1125
|
"roleAutoMatch.label": "启用角色自动匹配",
|
|
818
1126
|
"roleAutoMatch.hint": "规则未命中时,由模型自选最贴近的已声明角色",
|
|
819
1127
|
"roleAutoMatch.tooltip": "规则未命中时,模型会自动从已声明角色(id + persona)中选择最匹配者并注入该角色的链;关闭后未命中规则时按现状回落(inherit / rootChain)。",
|
|
820
|
-
"rootChain.label": "
|
|
821
|
-
"rootChain.
|
|
822
|
-
"
|
|
823
|
-
"rootChain.tooltip": "root 主代理失败时按此有序选择器列表依次降级;未配置时行为与未安装插件一致。",
|
|
824
|
-
"rootChain.selector.add": "添加选择器",
|
|
1128
|
+
"rootChain.label": "默认降级链",
|
|
1129
|
+
"rootChain.tooltip": "未命中任何分时槽时先走这条降级链;全部失败后落到下面的默认模型。",
|
|
1130
|
+
"defaultModel.label": "默认模型",
|
|
825
1131
|
"chains.selector.remove": "删除该选择器",
|
|
826
1132
|
"chains.selector.providerPlaceholder": "选择 provider",
|
|
827
1133
|
"chains.selector.modelPlaceholder": "选择 model",
|
|
828
1134
|
"chains.selector.wildcardLegacy": "该条目为通配(provider/*):选择具体模型后将转为精确条目",
|
|
829
1135
|
"chains.selector.noModelsStrict": "该 provider 暂无可用模型(目录查询失败),请改选其他 provider。",
|
|
1136
|
+
"mainAgent.label": "主代理",
|
|
1137
|
+
"subagents.label": "子代理",
|
|
1138
|
+
"timeSlots.label": "分时槽设置",
|
|
1139
|
+
"timeSlots.hint": "自上而下第一条命中生效;全时段行固定最后",
|
|
1140
|
+
"timeSlots.tz.label": "时区(UTC±)",
|
|
1141
|
+
"timeSlots.drag": "拖拽排序(或使用上下按钮)",
|
|
1142
|
+
"timeSlots.name": "名称",
|
|
1143
|
+
"timeSlots.expand": "展开该行",
|
|
1144
|
+
"timeSlots.collapse": "收起该行",
|
|
1145
|
+
"timeSlots.tooltip": "命中行的模型链成为 root 生效链(取代全时段链);未命中任何行时使用全时段链。分时切换是路由种子而非失败决策:不消耗冷却、不计入单步切换上限。",
|
|
1146
|
+
"timeSlots.addPreset": "添加预设",
|
|
1147
|
+
"timeSlots.addCustom": "添加自定义时段",
|
|
1148
|
+
"timeSlots.presetPlaceholder": "选择预设",
|
|
1149
|
+
"timeSlots.remove": "删除该时段行",
|
|
1150
|
+
"timeSlots.moveUp": "上移该时段行",
|
|
1151
|
+
"timeSlots.moveDown": "下移该时段行",
|
|
1152
|
+
"timeSlots.start": "开始(HH:mm)",
|
|
1153
|
+
"timeSlots.end": "结束(HH:mm)",
|
|
1154
|
+
"timeSlots.days": "星期",
|
|
1155
|
+
"timeSlots.days.hint": "不勾选 = 每天;可跨午夜",
|
|
1156
|
+
"timeSlots.preset.name": "预设",
|
|
1157
|
+
"timeSlots.preset.windowLabel": "时段(只读)",
|
|
1158
|
+
"timeSlots.preset.chainsOnly": "预设窗口已锁定:仅可编辑模型链",
|
|
1159
|
+
"timeSlots.preset.liang-peak.label": "梁文峰",
|
|
1160
|
+
"timeSlots.preset.liang-peak.window": "09:00–12:00 与 14:00–18:00(每天,UTC+8)",
|
|
1161
|
+
"timeSlots.preset.liang-valley.label": "梁文谷",
|
|
1162
|
+
"timeSlots.preset.liang-valley.window": "Liang Peak 之外的所有时间(每天,UTC+8)",
|
|
1163
|
+
"timeSlots.preset.glm-peak.label": "GLM峰",
|
|
1164
|
+
"timeSlots.preset.glm-peak.window": "周一至周五 14:00–18:00(UTC+8)",
|
|
1165
|
+
"timeSlots.preset.glm-valley.label": "GLM谷",
|
|
1166
|
+
"timeSlots.preset.glm-valley.window": "GLM Peak 之外的所有时间(UTC+8)",
|
|
1167
|
+
"timeSlots.preset.glm.note": "仅配置了 zai-coding-cn 时有效",
|
|
1168
|
+
"timeSlots.preset.highCost": "高消耗",
|
|
1169
|
+
"timeSlots.preset.multiplier": "x{n}",
|
|
1170
|
+
"timeSlots.active": "激活",
|
|
1171
|
+
"timeSlots.preset.glm.unconfigured": "(需配置 zai-coding-cn)",
|
|
1172
|
+
"timeSlots.day.sun": "日",
|
|
1173
|
+
"timeSlots.day.mon": "一",
|
|
1174
|
+
"timeSlots.day.tue": "二",
|
|
1175
|
+
"timeSlots.day.wed": "三",
|
|
1176
|
+
"timeSlots.day.thu": "四",
|
|
1177
|
+
"timeSlots.day.fri": "五",
|
|
1178
|
+
"timeSlots.day.sat": "六",
|
|
1179
|
+
"timeSlots.selector.add": "添加选择器",
|
|
1180
|
+
"allDay.hint": "全天链的最后一档兜底:官方 V4 Flash 或 V4 Pro 二选一",
|
|
1181
|
+
"allDay.flash": "官方 V4 Flash(deepseek-official/deepseek-v4-flash)",
|
|
1182
|
+
"allDay.pro": "官方 V4 Pro(deepseek-official/deepseek-v4-pro)",
|
|
1183
|
+
"allDay.nonconforming": "当前默认模型不合法:请选择官方 V4 Flash 或 V4 Pro 后保存",
|
|
830
1184
|
"roles.list.label": "角色实体",
|
|
831
1185
|
"roles.list.hint": "先声明角色,规则才能引用",
|
|
832
1186
|
"roles.list.tooltip": "角色 id 须匹配 /^[a-z0-9-]{1,32}$/ 且唯一;\"inherit\" 为保留字,不能用作角色 id。",
|
|
@@ -844,14 +1198,12 @@ window.__ModuleLoader__.load({
|
|
|
844
1198
|
"roles.fallback.none": "仅角色链(不追加 rootChain)",
|
|
845
1199
|
"roles.add": "添加角色",
|
|
846
1200
|
"roles.remove": "删除该角色",
|
|
1201
|
+
"roles.expand": "展开该角色",
|
|
1202
|
+
"roles.collapse": "收起该角色",
|
|
847
1203
|
"roles.selector.add": "添加选择器",
|
|
848
1204
|
"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",
|
|
1205
|
+
"roles.rules.hint": "仅对子代理生效:顺序匹配 provider/model,未命中 → inherit(root 链)",
|
|
1206
|
+
"roles.rules.tooltip": "规则仅对子代理生效(root 请求不匹配规则):命中后走对应角色的链;未命中走内置 inherit(rootChain)。",
|
|
855
1207
|
"roles.rule.provider": "provider",
|
|
856
1208
|
"roles.rule.provider.any": "任意",
|
|
857
1209
|
"roles.rule.model": "model",
|
|
@@ -869,6 +1221,14 @@ window.__ModuleLoader__.load({
|
|
|
869
1221
|
"validation.ruleRoleUndeclared": "规则引用了未声明的角色 \"{role}\"",
|
|
870
1222
|
"validation.ruleRoleRequired": "规则未选择角色:请选择目标角色,或删除该行",
|
|
871
1223
|
"validation.roleChainRequired": "角色 \"{id}\" 未配置模型:请至少添加一条链选择器(模型配置)",
|
|
1224
|
+
"validation.allDayRequired": "默认模型必须二选一:官方 V4 Flash 或 V4 Pro",
|
|
1225
|
+
"validation.slotChainRequired": "分时槽未配置模型:请至少添加一条链选择器",
|
|
1226
|
+
"validation.slotWindow": "分时槽开始/结束时间须为 HH:mm 格式",
|
|
1227
|
+
"validation.slotDays": "星期取值须为 0–6 的整数",
|
|
1228
|
+
"validation.slotKind": "分时槽 kind 须为 \"preset\" 或 \"custom\"",
|
|
1229
|
+
"validation.slotPresetUnknown": "未知的分时槽预设 \"{preset}\"",
|
|
1230
|
+
"validation.slotPresetDuplicate": "预设 \"{preset}\" 已存在:每个预设只能添加一行",
|
|
1231
|
+
"validation.slotPresetFrozen": "预设窗口是冻结代码常量:预设行不能携带 start/end/days",
|
|
872
1232
|
"validation.selector": "选择器 \"{entry}\" 非法:{message}",
|
|
873
1233
|
"legacy.banner": "检测到旧格式配置字段({keys}):已按新模型展示,请按 docs/configuration.md 迁移表手工改写;插件不会自动改写配置。",
|
|
874
1234
|
"catalog.empty": "暂无可用模型:请先在模型页添加模型,添加后此处将自动可选。",
|
|
@@ -905,12 +1265,6 @@ window.__ModuleLoader__.load({
|
|
|
905
1265
|
"save.saving": "保存中…",
|
|
906
1266
|
"save.error": "保存失败:{message}",
|
|
907
1267
|
"close": "关闭",
|
|
908
|
-
"reset": "恢复默认",
|
|
909
|
-
"reset.confirmTitle": "恢复默认配置",
|
|
910
|
-
"reset.confirm": "恢复后 fallbacks 配置将回到插件默认值,当前编辑内容会丢失。",
|
|
911
|
-
"reset.confirm.cancel": "取消",
|
|
912
|
-
"reset.confirm.action": "恢复默认",
|
|
913
|
-
"reset.saving": "恢复中…",
|
|
914
1268
|
"loading": "加载中…",
|
|
915
1269
|
"unavailable": "fallbacks 配置通道暂不可达:以下显示默认配置(或上次读取值),可尝试保存;保存失败会在此处如实提示。",
|
|
916
1270
|
"error.generic": "出错:{message}"
|
|
@@ -956,16 +1310,62 @@ window.__ModuleLoader__.load({
|
|
|
956
1310
|
"roleAutoMatch.label": "Enable role auto-match",
|
|
957
1311
|
"roleAutoMatch.hint": "On rules-miss, the model picks the closest declared role",
|
|
958
1312
|
"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",
|
|
1313
|
+
"rootChain.label": "Default fallback chain",
|
|
1314
|
+
"rootChain.tooltip": "Walked first whenever no time slot matches; if every entry fails, the default model below is the last fallback.",
|
|
1315
|
+
"defaultModel.label": "Default model",
|
|
964
1316
|
"chains.selector.remove": "Remove this selector",
|
|
965
1317
|
"chains.selector.providerPlaceholder": "Select provider",
|
|
966
1318
|
"chains.selector.modelPlaceholder": "Select model",
|
|
967
1319
|
"chains.selector.wildcardLegacy": "This entry is a wildcard (provider/*): picking a model converts it to an exact entry",
|
|
968
1320
|
"chains.selector.noModelsStrict": "No models available for this provider (catalog lookup failed); pick another provider.",
|
|
1321
|
+
"mainAgent.label": "Main agent",
|
|
1322
|
+
"subagents.label": "Subagents",
|
|
1323
|
+
"timeSlots.label": "Time slots",
|
|
1324
|
+
"timeSlots.hint": "First match from top to bottom wins; the all-day row is always last",
|
|
1325
|
+
"timeSlots.tz.label": "Timezone (UTC±)",
|
|
1326
|
+
"timeSlots.drag": "Drag to reorder (or use the up/down buttons)",
|
|
1327
|
+
"timeSlots.name": "Name",
|
|
1328
|
+
"timeSlots.expand": "Expand this row",
|
|
1329
|
+
"timeSlots.collapse": "Collapse this row",
|
|
1330
|
+
"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.",
|
|
1331
|
+
"timeSlots.addPreset": "Add preset",
|
|
1332
|
+
"timeSlots.addCustom": "Add custom time slot",
|
|
1333
|
+
"timeSlots.presetPlaceholder": "Select a preset",
|
|
1334
|
+
"timeSlots.remove": "Remove this time-slot row",
|
|
1335
|
+
"timeSlots.moveUp": "Move this time-slot row up",
|
|
1336
|
+
"timeSlots.moveDown": "Move this time-slot row down",
|
|
1337
|
+
"timeSlots.start": "Start (HH:mm)",
|
|
1338
|
+
"timeSlots.end": "End (HH:mm)",
|
|
1339
|
+
"timeSlots.days": "Days",
|
|
1340
|
+
"timeSlots.days.hint": "None selected = every day; may wrap midnight",
|
|
1341
|
+
"timeSlots.preset.name": "Preset",
|
|
1342
|
+
"timeSlots.preset.windowLabel": "Window (read-only)",
|
|
1343
|
+
"timeSlots.preset.chainsOnly": "Preset windows are frozen: only the model chain is editable",
|
|
1344
|
+
"timeSlots.preset.liang-peak.label": "Liang Peak",
|
|
1345
|
+
"timeSlots.preset.liang-peak.window": "09:00–12:00 & 14:00–18:00 (every day, UTC+8)",
|
|
1346
|
+
"timeSlots.preset.liang-valley.label": "Liang Valley",
|
|
1347
|
+
"timeSlots.preset.liang-valley.window": "All times outside Liang Peak (every day, UTC+8)",
|
|
1348
|
+
"timeSlots.preset.glm-peak.label": "GLM Peak",
|
|
1349
|
+
"timeSlots.preset.glm-peak.window": "Monday–Friday 14:00–18:00 (UTC+8)",
|
|
1350
|
+
"timeSlots.preset.glm-valley.label": "GLM Valley",
|
|
1351
|
+
"timeSlots.preset.glm-valley.window": "All times outside GLM Peak (UTC+8)",
|
|
1352
|
+
"timeSlots.preset.glm.note": "Only effective when zai-coding-cn is configured",
|
|
1353
|
+
"timeSlots.preset.highCost": "High Cost",
|
|
1354
|
+
"timeSlots.preset.multiplier": "x{n}",
|
|
1355
|
+
"timeSlots.active": "Active",
|
|
1356
|
+
"timeSlots.preset.glm.unconfigured": " (requires zai-coding-cn)",
|
|
1357
|
+
"timeSlots.day.sun": "Sun",
|
|
1358
|
+
"timeSlots.day.mon": "Mon",
|
|
1359
|
+
"timeSlots.day.tue": "Tue",
|
|
1360
|
+
"timeSlots.day.wed": "Wed",
|
|
1361
|
+
"timeSlots.day.thu": "Thu",
|
|
1362
|
+
"timeSlots.day.fri": "Fri",
|
|
1363
|
+
"timeSlots.day.sat": "Sat",
|
|
1364
|
+
"timeSlots.selector.add": "Add selector",
|
|
1365
|
+
"allDay.hint": "Last-resort fallback of the all-day chain: official V4 Flash or Pro (pick exactly one)",
|
|
1366
|
+
"allDay.flash": "Official V4 Flash (deepseek-official/deepseek-v4-flash)",
|
|
1367
|
+
"allDay.pro": "Official V4 Pro (deepseek-official/deepseek-v4-pro)",
|
|
1368
|
+
"allDay.nonconforming": "The current default model is not valid: pick official V4 Flash or Pro before saving",
|
|
969
1369
|
"roles.list.label": "Declared roles",
|
|
970
1370
|
"roles.list.hint": "Declare roles before rules can reference them",
|
|
971
1371
|
"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 +1383,12 @@ window.__ModuleLoader__.load({
|
|
|
983
1383
|
"roles.fallback.none": "Role chain only (no rootChain)",
|
|
984
1384
|
"roles.add": "Add role",
|
|
985
1385
|
"roles.remove": "Remove this role",
|
|
1386
|
+
"roles.expand": "Expand this role",
|
|
1387
|
+
"roles.collapse": "Collapse this role",
|
|
986
1388
|
"roles.selector.add": "Add selector",
|
|
987
1389
|
"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",
|
|
1390
|
+
"roles.rules.hint": "Subagents only: matches provider/model in order; no match → inherit (root chain)",
|
|
1391
|
+
"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
1392
|
"roles.rule.provider": "provider",
|
|
995
1393
|
"roles.rule.provider.any": "Any",
|
|
996
1394
|
"roles.rule.model": "model",
|
|
@@ -1008,6 +1406,14 @@ window.__ModuleLoader__.load({
|
|
|
1008
1406
|
"validation.ruleRoleUndeclared": "Rule references undeclared role \"{role}\"",
|
|
1009
1407
|
"validation.ruleRoleRequired": "Rule has no role selected: pick a target role, or remove the row",
|
|
1010
1408
|
"validation.roleChainRequired": "Role \"{id}\" has no model config: add at least one chain entry",
|
|
1409
|
+
"validation.allDayRequired": "The default model must be exactly one official V4 model (V4 Flash or V4 Pro)",
|
|
1410
|
+
"validation.slotChainRequired": "Time-slot row has no models: add at least one chain entry",
|
|
1411
|
+
"validation.slotWindow": "Time-slot start/end must use HH:mm format",
|
|
1412
|
+
"validation.slotDays": "Days must be integers 0–6",
|
|
1413
|
+
"validation.slotKind": "Time-slot kind must be \"preset\" or \"custom\"",
|
|
1414
|
+
"validation.slotPresetUnknown": "Unknown time-slot preset \"{preset}\"",
|
|
1415
|
+
"validation.slotPresetDuplicate": "Preset \"{preset}\" already exists: at most one row per preset",
|
|
1416
|
+
"validation.slotPresetFrozen": "Preset windows are frozen code constants: a preset row cannot carry start/end/days",
|
|
1011
1417
|
"validation.selector": "Invalid selector \"{entry}\": {message}",
|
|
1012
1418
|
"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
1419
|
"catalog.empty": "No models yet: add a model on the Models page first; options will appear here automatically.",
|
|
@@ -1044,12 +1450,6 @@ window.__ModuleLoader__.load({
|
|
|
1044
1450
|
"save.saving": "Saving…",
|
|
1045
1451
|
"save.error": "Save failed: {message}",
|
|
1046
1452
|
"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
1453
|
"loading": "Loading…",
|
|
1054
1454
|
"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
1455
|
"error.generic": "Error: {message}"
|
|
@@ -1092,7 +1492,7 @@ window.__ModuleLoader__.load({
|
|
|
1092
1492
|
}
|
|
1093
1493
|
//#endregion
|
|
1094
1494
|
//#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";
|
|
1495
|
+
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
1496
|
const tagId$2 = "dsh-llm-fallbacks/FallbacksCard.module.css";
|
|
1097
1497
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
1098
1498
|
const tag = document.createElement("style");
|
|
@@ -1113,7 +1513,6 @@ window.__ModuleLoader__.load({
|
|
|
1113
1513
|
"body": "_dbaa7975_body",
|
|
1114
1514
|
"readOnly": "_4e39cf17_readOnly",
|
|
1115
1515
|
"pending": "_99bf7f3c_pending",
|
|
1116
|
-
"footer": "_114985b2_footer",
|
|
1117
1516
|
"notice": "_9860a5b1_notice",
|
|
1118
1517
|
"legacyNotice": "_5006d43e_legacyNotice",
|
|
1119
1518
|
"error": "_21918751_error",
|
|
@@ -1127,13 +1526,19 @@ window.__ModuleLoader__.load({
|
|
|
1127
1526
|
"fieldset": "_94c91bfd_fieldset",
|
|
1128
1527
|
"field": "_67826267_field",
|
|
1129
1528
|
"fieldLabel": "_13e68c3f_fieldLabel",
|
|
1529
|
+
"sectionHeading": "_ba240d82_sectionHeading",
|
|
1530
|
+
"sectionHeadingText": "_ddbc1b49_sectionHeadingText",
|
|
1531
|
+
"sectionActions": "_c41f9db7_sectionActions",
|
|
1130
1532
|
"sectionToggle": "_b116c758_sectionToggle",
|
|
1131
1533
|
"sectionToggleText": "_a5313fdf_sectionToggleText",
|
|
1132
1534
|
"hint": "_4bc809b8_hint",
|
|
1133
1535
|
"defaultNote": "_579f813a_defaultNote",
|
|
1536
|
+
"slotPresetName": "_b1962759_slotPresetName",
|
|
1134
1537
|
"infoHint": "_a6244318_infoHint",
|
|
1135
1538
|
"infoHintDisabled": "_e655c840_infoHintDisabled",
|
|
1136
1539
|
"optionRow": "_a2521bb0_optionRow",
|
|
1540
|
+
"dayRow": "_c4ecbdf3_dayRow",
|
|
1541
|
+
"dayCell": "_0330c1ed_dayCell",
|
|
1137
1542
|
"input": "_f9d86f7b_input",
|
|
1138
1543
|
"inputTextarea": "_3a9b42fd_inputTextarea",
|
|
1139
1544
|
"inputInvalid": "_7b60337a_inputInvalid",
|
|
@@ -1144,21 +1549,34 @@ window.__ModuleLoader__.load({
|
|
|
1144
1549
|
"cardFoot": "_224b1387_cardFoot",
|
|
1145
1550
|
"ruleGrid": "_8e220e07_ruleGrid",
|
|
1146
1551
|
"ruleCell": "_24a12a2f_ruleCell",
|
|
1552
|
+
"collapseRow": "_86bc52d2_collapseRow",
|
|
1553
|
+
"collapseToggle": "_a73efcc6_collapseToggle",
|
|
1554
|
+
"collapseTitle": "_af017718_collapseTitle",
|
|
1555
|
+
"collapseMeta": "_2cabe603_collapseMeta",
|
|
1556
|
+
"slotTag": "_7b04f727_slotTag",
|
|
1557
|
+
"slotTagHighCost": "_c381e792_slotTagHighCost",
|
|
1558
|
+
"slotTagMultiplier": "_23bdb6fc_slotTagMultiplier",
|
|
1559
|
+
"slotTagActive": "_f000eed9_slotTagActive",
|
|
1560
|
+
"dragHandle": "_cd905ce5_dragHandle",
|
|
1561
|
+
"dragHandleIcon": "_49f0c4f0_dragHandleIcon",
|
|
1562
|
+
"slotCardDragging": "_fee63b7e_slotCardDragging",
|
|
1563
|
+
"slotCardOver": "_6f108491_slotCardOver",
|
|
1147
1564
|
"ruleCellLabel": "_1014c097_ruleCellLabel",
|
|
1148
1565
|
"chainSelectors": "_15a12620_chainSelectors",
|
|
1149
1566
|
"selectorRow": "_240cbbf8_selectorRow",
|
|
1150
1567
|
"iconButton": "_70effa64_iconButton",
|
|
1151
1568
|
"iconButtonDanger": "_a0968257_iconButtonDanger",
|
|
1152
1569
|
"addButton": "_28202c90_addButton",
|
|
1570
|
+
"slotAddRow": "_6a2bd54c_slotAddRow",
|
|
1571
|
+
"rowActions": "_4e77523e_rowActions",
|
|
1153
1572
|
"primaryButton": "_747fd56d_primaryButton",
|
|
1154
1573
|
"secondaryButton": "_7e855445_secondaryButton",
|
|
1574
|
+
"sectionAction": "_238d19be_sectionAction",
|
|
1155
1575
|
"statusBlock": "_fbd045e0_statusBlock",
|
|
1156
1576
|
"statusTitle": "_d4f70367_statusTitle",
|
|
1157
1577
|
"statusLine": "_8ab300ed_statusLine",
|
|
1158
1578
|
"statusLineLabel": "_e8cedbf5_statusLineLabel",
|
|
1159
|
-
"offNotice": "_b48dfcba_offNotice"
|
|
1160
|
-
"resetDialog": "_ec8bd970_resetDialog",
|
|
1161
|
-
"confirmDanger": "_8677165c_confirmDanger"
|
|
1579
|
+
"offNotice": "_b48dfcba_offNotice"
|
|
1162
1580
|
};
|
|
1163
1581
|
//#endregion
|
|
1164
1582
|
//#region src/client/FallbacksCard.tsx
|
|
@@ -1176,12 +1594,22 @@ window.__ModuleLoader__.load({
|
|
|
1176
1594
|
* description, with a dirty "unsaved" pill and a rotating chevron
|
|
1177
1595
|
* (`IconChevronDownOutline14` from ui-primitives — a CLIENT_EXTERNALS value
|
|
1178
1596
|
* import), `aria-expanded`/`aria-label` like the upstream header; a divider
|
|
1179
|
-
* under the header; then the form content
|
|
1180
|
-
*
|
|
1181
|
-
*
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
* (
|
|
1597
|
+
* under the header; then the form content. PR #62 UX round 2: the card
|
|
1598
|
+
* footer is gone — each big section (主代理 / 子代理 / 高级选项) carries its
|
|
1599
|
+
* own Save/Discard actions beside its heading (高级选项: inside the expanded
|
|
1600
|
+
* body) and its own validation / save-error surface. PR #62 UX round 3:
|
|
1601
|
+
* each section's Save writes ONLY that section's fields — 主代理 owns
|
|
1602
|
+
* rootChain / timeSlots / tz (+ the card-level `enabled`), 子代理 owns
|
|
1603
|
+
* roles, 高级选项 owns the advanced scalars; the patch spreads the last
|
|
1604
|
+
* ACCEPTED config for every other section, so a 主代理 Save can never
|
|
1605
|
+
* ride along an unsaved 子代理 edit (and vice versa) — and validation /
|
|
1606
|
+
* the dirty gate apply per section too (a bad role id never blocks 主代理,
|
|
1607
|
+
* and only the saved section's Discard reverts that section's edits).
|
|
1608
|
+
* Save/discard disabled terms: save = `!sectionDirty || saving ||
|
|
1609
|
+
* !writable`, discard = `!sectionDirty || saving` (KD-U1). Disclosure is
|
|
1610
|
+
* card-local state:
|
|
1611
|
+
* which card a user has open is a reading gesture, and staged edits outlive
|
|
1612
|
+
* collapsing — the pill rides the header (upstream rationale).
|
|
1185
1613
|
*
|
|
1186
1614
|
* The form body is the two-block editing surface (spec §8): the `enabled`
|
|
1187
1615
|
* checkbox row, the 6 top-level scalar fields (trigger codes / revert
|
|
@@ -1197,13 +1625,14 @@ window.__ModuleLoader__.load({
|
|
|
1197
1625
|
* non-empty `state.legacyKeys` renders the migration banner at the top of
|
|
1198
1626
|
* the card body. The row editors keep their filled editorCard surface
|
|
1199
1627
|
* inside the card, with `--dsw-alias-*` tokens throughout. The reset-
|
|
1200
|
-
* to-defaults
|
|
1201
|
-
* the
|
|
1628
|
+
* to-defaults affordance is GONE from the card (PR #62 UX round 3) — the
|
|
1629
|
+
* gateway RPC `fallbacks/reset` and the store `resetToDefaults()` stay as
|
|
1630
|
+
* host APIs (store/gateway tests unchanged), only the card UI was removed.
|
|
1202
1631
|
*
|
|
1203
1632
|
* The page-only chrome is gone (720px column wrapper, title/intro banners,
|
|
1204
1633
|
* page-bottom status block): the AC-7 read-only status (derived effective
|
|
1205
|
-
* model + recent-switch summary) is folded into the card body
|
|
1206
|
-
*
|
|
1634
|
+
* model + recent-switch summary) is folded into the card body, and the
|
|
1635
|
+
* plugin-config section owns the column width.
|
|
1207
1636
|
*
|
|
1208
1637
|
* Degraded/error/loading states keep the same card chrome (KD-U3): the
|
|
1209
1638
|
* header always renders title+description+chevron, and the body carries the
|
|
@@ -1217,8 +1646,11 @@ window.__ModuleLoader__.load({
|
|
|
1217
1646
|
* 'error'`) also forces the body open with an error notice and — when the
|
|
1218
1647
|
* form is inert (`!writable`, i.e. the load never landed) — a Retry button;
|
|
1219
1648
|
* a save failure keeps the editable form so the Save action itself is the
|
|
1220
|
-
* retry
|
|
1221
|
-
*
|
|
1649
|
+
* retry. PR #62 UX round 2: the single `state.error` surface is split by
|
|
1650
|
+
* origin — a LOAD failure keeps the card-top notice (with Retry when
|
|
1651
|
+
* inert), while a WRITE failure renders under the section whose Save was
|
|
1652
|
+
* last clicked (`lastSaveSection`), unlike the advisor's separate
|
|
1653
|
+
* apply-failure hints.
|
|
1222
1654
|
*
|
|
1223
1655
|
* The degraded derivation is latched in the card (the store stays untouched):
|
|
1224
1656
|
* `present` only ever changes inside the store's `accept()`, so the settled
|
|
@@ -1228,6 +1660,77 @@ window.__ModuleLoader__.load({
|
|
|
1228
1660
|
* implemented without a store change); on a first mount the latch is false,
|
|
1229
1661
|
* so the healthy card starts (and stays) collapsed through its first load.
|
|
1230
1662
|
*/
|
|
1663
|
+
const ALL_DAY_FLASH = "deepseek-official/deepseek-v4-flash";
|
|
1664
|
+
const ALL_DAY_PRO = "deepseek-official/deepseek-v4-pro";
|
|
1665
|
+
const SLOT_PRESET_IDS = [
|
|
1666
|
+
"liang-peak",
|
|
1667
|
+
"liang-valley",
|
|
1668
|
+
"glm-peak",
|
|
1669
|
+
"glm-valley"
|
|
1670
|
+
];
|
|
1671
|
+
/** Custom-row day toggle order (index = weekday, 0=Sunday); display copy lives in the dictionaries. */
|
|
1672
|
+
const SLOT_WEEKDAYS = [
|
|
1673
|
+
"sun",
|
|
1674
|
+
"mon",
|
|
1675
|
+
"tue",
|
|
1676
|
+
"wed",
|
|
1677
|
+
"thu",
|
|
1678
|
+
"fri",
|
|
1679
|
+
"sat"
|
|
1680
|
+
];
|
|
1681
|
+
/** IANA timezone of this renderer (browser / host). */
|
|
1682
|
+
function hostTimeZone() {
|
|
1683
|
+
try {
|
|
1684
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
1685
|
+
return typeof tz === "string" && tz !== "" ? tz : "UTC";
|
|
1686
|
+
} catch {
|
|
1687
|
+
return "UTC";
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
/** `UTC+8` / `UTC-4` for an IANA id (current offset, DST-honest). */
|
|
1691
|
+
function tzUtcOffset(tz) {
|
|
1692
|
+
try {
|
|
1693
|
+
const name = new Intl.DateTimeFormat("en-US", {
|
|
1694
|
+
timeZone: tz,
|
|
1695
|
+
timeZoneName: "shortOffset"
|
|
1696
|
+
}).formatToParts(/* @__PURE__ */ new Date()).find((part) => part.type === "timeZoneName")?.value;
|
|
1697
|
+
if (name === void 0 || name === "") return "";
|
|
1698
|
+
return name.replace(/^GMT/, "UTC");
|
|
1699
|
+
} catch {
|
|
1700
|
+
return "";
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
/** Read-only custom-row copy: `Asia/Shanghai (UTC+8)`. */
|
|
1704
|
+
function tzDisplayLabel(tz) {
|
|
1705
|
+
const offset = tzUtcOffset(tz);
|
|
1706
|
+
return offset === "" ? tz : `${tz} (${offset})`;
|
|
1707
|
+
}
|
|
1708
|
+
/** Persist tz: presets lock UTC+8; custom-only uses the host zone; else keep the accepted value. */
|
|
1709
|
+
function resolvedSlotTz(rows, fallback) {
|
|
1710
|
+
if (rows.some((row) => row.kind === "preset")) return "Asia/Shanghai";
|
|
1711
|
+
if (rows.some((row) => row.kind === "custom")) return hostTimeZone();
|
|
1712
|
+
return fallback === "" ? "Asia/Shanghai" : fallback;
|
|
1713
|
+
}
|
|
1714
|
+
/** Strict 24h `HH:mm` — the resolver's HHMM_RE twin (drift-guarded by the gateway reject-on-save). */
|
|
1715
|
+
const HHMM_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
1716
|
+
/**
|
|
1717
|
+
* The 默认模型 value for a chain: the official V4 id when the chain TAIL
|
|
1718
|
+
* is that model (Flash XOR Pro — leading 默认降级链 entries allowed);
|
|
1719
|
+
* `''` for an empty chain or a chain whose last entry is not official
|
|
1720
|
+
* (the panel reads back unselected and save validation blocks the value).
|
|
1721
|
+
*/
|
|
1722
|
+
function allDayModelOf(chain) {
|
|
1723
|
+
const tail = chain.length >= 1 ? chain[chain.length - 1] : void 0;
|
|
1724
|
+
return tail === ALL_DAY_FLASH || tail === ALL_DAY_PRO ? tail : "";
|
|
1725
|
+
}
|
|
1726
|
+
/**
|
|
1727
|
+
* The 默认降级链 editor row: the leading entries BEFORE the official-V4
|
|
1728
|
+
* tail, or the whole chain while the tail is not official (the draft
|
|
1729
|
+
* rides the accepted value until a 默认模型 pick).
|
|
1730
|
+
*/
|
|
1731
|
+
function allDayChainRowOf(chain, catalog) {
|
|
1732
|
+
return rootChainToRows(allDayModelOf(chain) === "" ? chain : chain.slice(0, -1), catalog)[0];
|
|
1733
|
+
}
|
|
1231
1734
|
/** Split scalars from the row editors (rootChain / role entities / role rules). */
|
|
1232
1735
|
function scalarsOf(config) {
|
|
1233
1736
|
return {
|
|
@@ -1237,7 +1740,8 @@ window.__ModuleLoader__.load({
|
|
|
1237
1740
|
revertPolicy: config.revertPolicy,
|
|
1238
1741
|
maxSwitchesPerStep: config.maxSwitchesPerStep,
|
|
1239
1742
|
alwaysModeRetryCap: config.alwaysModeRetryCap,
|
|
1240
|
-
roleAutoMatch: config.roleAutoMatch
|
|
1743
|
+
roleAutoMatch: config.roleAutoMatch,
|
|
1744
|
+
tz: config.tz ?? "Asia/Shanghai"
|
|
1241
1745
|
};
|
|
1242
1746
|
}
|
|
1243
1747
|
/**
|
|
@@ -1255,13 +1759,22 @@ window.__ModuleLoader__.load({
|
|
|
1255
1759
|
* `true` even for a legacy config that never declared the key — so the
|
|
1256
1760
|
* toggle always renders (default on) and a save persists the resolved value
|
|
1257
1761
|
* (AC-7 re-scope, PM decision 2026-08-17 Option A).
|
|
1762
|
+
*
|
|
1763
|
+
* All-day: rootChain is composed from the 默认降级链 editor's leading
|
|
1764
|
+
* selectors plus the 默认模型 tail (exactly one official V4 — Flash XOR
|
|
1765
|
+
* Pro). While no tail is selected the ACCEPTED chain rides through
|
|
1766
|
+
* untouched. `timeSlots` is rebuilt from the slot rows every render. `tz`
|
|
1767
|
+
* is a card scalar: preset rows lock it to Asia/Shanghai; custom rows
|
|
1768
|
+
* follow the selected timezone.
|
|
1258
1769
|
*/
|
|
1259
|
-
function assembleConfig(scalars,
|
|
1770
|
+
function assembleConfig(scalars, allDayModel, acceptedRootChain, allDayChainRow, roleRows, ruleRows, originalRoles, presets, roleAutoMatch, timeSlotRows) {
|
|
1260
1771
|
const list = mergeRoleExtras(roleRows, originalRoles);
|
|
1772
|
+
const trailingChain = rowsToRootChain([allDayChainRow]);
|
|
1773
|
+
const tz = resolvedSlotTz(timeSlotRows, scalars.tz);
|
|
1261
1774
|
return {
|
|
1262
1775
|
enabled: scalars.enabled,
|
|
1263
1776
|
triggerCodes: [...scalars.triggerCodes],
|
|
1264
|
-
rootChain:
|
|
1777
|
+
rootChain: allDayModel === "" ? [...acceptedRootChain] : [...trailingChain, allDayModel],
|
|
1265
1778
|
roles: {
|
|
1266
1779
|
list,
|
|
1267
1780
|
rules: rowsToRules(ruleRows)
|
|
@@ -1271,7 +1784,17 @@ window.__ModuleLoader__.load({
|
|
|
1271
1784
|
maxSwitchesPerStep: scalars.maxSwitchesPerStep,
|
|
1272
1785
|
alwaysModeRetryCap: scalars.alwaysModeRetryCap,
|
|
1273
1786
|
...presets === void 0 ? {} : { presets },
|
|
1274
|
-
roleAutoMatch
|
|
1787
|
+
roleAutoMatch,
|
|
1788
|
+
timeSlots: rowsToTimeSlots(timeSlotRows),
|
|
1789
|
+
tz
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
/** An empty per-section validation-error record (the clean-draft shape). */
|
|
1793
|
+
function emptyValidationErrors() {
|
|
1794
|
+
return {
|
|
1795
|
+
main: [],
|
|
1796
|
+
sub: [],
|
|
1797
|
+
advanced: []
|
|
1275
1798
|
};
|
|
1276
1799
|
}
|
|
1277
1800
|
/**
|
|
@@ -1279,9 +1802,14 @@ window.__ModuleLoader__.load({
|
|
|
1279
1802
|
* role id format/reserved word/duplicates, undeclared rule role references
|
|
1280
1803
|
* (only reachable through the synthetic outside option — the dropdown
|
|
1281
1804
|
* itself constrains normal edits), and illegal selector entries in
|
|
1282
|
-
* rootChain and role chains. Returns one localized message per violation
|
|
1283
|
-
*
|
|
1284
|
-
*
|
|
1805
|
+
* rootChain and role chains. Returns one localized message per violation,
|
|
1806
|
+
* bucketed by the section that owns the offending field (PR #62 UX round
|
|
1807
|
+
* 2 — 主代理: allDay / timeSlots / slot* / tz / default model / default
|
|
1808
|
+
* chain; 子代理: role* / rule*; 高级选项: trigger / cooldown / revert /
|
|
1809
|
+
* always / roleAutoMatch — the scalars are never validated, so the
|
|
1810
|
+
* advanced bucket stays empty today). A non-empty result blocks
|
|
1811
|
+
* {@link save} — the draft is never written. `persona` is free text and
|
|
1812
|
+
* never validated.
|
|
1285
1813
|
*
|
|
1286
1814
|
* `seededIds` is the live trimmed-id → overridden map derived from
|
|
1287
1815
|
* `state.seeds` (spec §9.4): the empty-chain block relaxes for seeded ids
|
|
@@ -1290,33 +1818,57 @@ window.__ModuleLoader__.load({
|
|
|
1290
1818
|
* behavior is byte-identical.
|
|
1291
1819
|
*/
|
|
1292
1820
|
function validateDraft(draft, t, seededIds) {
|
|
1293
|
-
const errors =
|
|
1821
|
+
const errors = emptyValidationErrors();
|
|
1294
1822
|
const declaredIds = /* @__PURE__ */ new Set();
|
|
1295
1823
|
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 }));
|
|
1824
|
+
if (!ROLE_ID_PATTERN.test(role.id)) errors.sub.push(t("validation.roleIdFormat", { id: role.id }));
|
|
1825
|
+
if (role.id === "inherit") errors.sub.push(t("validation.roleIdReserved"));
|
|
1826
|
+
if (declaredIds.has(role.id)) errors.sub.push(t("validation.roleIdDuplicate", { id: role.id }));
|
|
1299
1827
|
declaredIds.add(role.id);
|
|
1300
1828
|
for (const entry of role.chain ?? []) try {
|
|
1301
1829
|
parseSelector(entry);
|
|
1302
1830
|
} catch (error) {
|
|
1303
|
-
errors.push(t("validation.selector", {
|
|
1831
|
+
errors.sub.push(t("validation.selector", {
|
|
1304
1832
|
entry,
|
|
1305
1833
|
message: error.message
|
|
1306
1834
|
}));
|
|
1307
1835
|
}
|
|
1308
|
-
if ((role.chain ?? []).length === 0 && !seededIds.has(role.id.trim())) errors.push(t("validation.roleChainRequired", { id: role.id }));
|
|
1836
|
+
if ((role.chain ?? []).length === 0 && !seededIds.has(role.id.trim())) errors.sub.push(t("validation.roleChainRequired", { id: role.id }));
|
|
1309
1837
|
}
|
|
1838
|
+
const allDayTail = draft.rootChain.length >= 1 ? draft.rootChain[draft.rootChain.length - 1] : void 0;
|
|
1839
|
+
if (allDayTail !== ALL_DAY_FLASH && allDayTail !== ALL_DAY_PRO) errors.main.push(t("validation.allDayRequired"));
|
|
1310
1840
|
for (const entry of draft.rootChain) try {
|
|
1311
1841
|
parseSelector(entry);
|
|
1312
1842
|
} catch (error) {
|
|
1313
|
-
errors.push(t("validation.selector", {
|
|
1843
|
+
errors.main.push(t("validation.selector", {
|
|
1314
1844
|
entry,
|
|
1315
1845
|
message: error.message
|
|
1316
1846
|
}));
|
|
1317
1847
|
}
|
|
1848
|
+
const seenSlotPresets = /* @__PURE__ */ new Set();
|
|
1849
|
+
for (const row of draft.timeSlots ?? []) {
|
|
1850
|
+
if (row.kind !== "preset" && row.kind !== "custom") errors.main.push(t("validation.slotKind"));
|
|
1851
|
+
if (row.kind === "preset") {
|
|
1852
|
+
if (typeof row.preset !== "string" || !SLOT_PRESET_IDS.includes(row.preset)) errors.main.push(t("validation.slotPresetUnknown", { preset: row.preset }));
|
|
1853
|
+
else if (seenSlotPresets.has(row.preset)) errors.main.push(t("validation.slotPresetDuplicate", { preset: row.preset }));
|
|
1854
|
+
else seenSlotPresets.add(row.preset);
|
|
1855
|
+
if (row.start !== void 0 || row.end !== void 0 || row.days !== void 0 && row.days.length > 0) errors.main.push(t("validation.slotPresetFrozen"));
|
|
1856
|
+
} else if (row.kind === "custom") {
|
|
1857
|
+
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"));
|
|
1858
|
+
if (row.days !== void 0 && row.days.some((day) => !Number.isInteger(day) || day < 0 || day > 6)) errors.main.push(t("validation.slotDays"));
|
|
1859
|
+
}
|
|
1860
|
+
for (const entry of row.chain) try {
|
|
1861
|
+
parseSelector(entry);
|
|
1862
|
+
} catch (error) {
|
|
1863
|
+
errors.main.push(t("validation.selector", {
|
|
1864
|
+
entry,
|
|
1865
|
+
message: error.message
|
|
1866
|
+
}));
|
|
1867
|
+
}
|
|
1868
|
+
if (row.chain.length === 0) errors.main.push(t("validation.slotChainRequired"));
|
|
1869
|
+
}
|
|
1318
1870
|
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 }));
|
|
1871
|
+
for (const rule of draft.roles.rules) if (!validTargets.has(rule.role)) errors.sub.push(t("validation.ruleRoleUndeclared", { role: rule.role }));
|
|
1320
1872
|
return errors;
|
|
1321
1873
|
}
|
|
1322
1874
|
/**
|
|
@@ -1345,6 +1897,20 @@ window.__ModuleLoader__.load({
|
|
|
1345
1897
|
const parsed = Number.parseInt(raw, 10);
|
|
1346
1898
|
return Number.isNaN(parsed) ? 0 : Math.max(0, parsed);
|
|
1347
1899
|
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Custom time-slot rows whose window is not valid `HH:mm` — drives the
|
|
1902
|
+
* inline red border after a blocked save attempt (same derivation pattern
|
|
1903
|
+
* as {@link collectInvalidRoleIds}: one pass per render, index lookup per
|
|
1904
|
+
* row).
|
|
1905
|
+
*/
|
|
1906
|
+
function collectInvalidSlotRows(rows) {
|
|
1907
|
+
const invalid = /* @__PURE__ */ new Set();
|
|
1908
|
+
rows.forEach((row, index) => {
|
|
1909
|
+
if (row.kind === "preset") return;
|
|
1910
|
+
if (!HHMM_RE.test(row.start) || !HHMM_RE.test(row.end)) invalid.add(index);
|
|
1911
|
+
});
|
|
1912
|
+
return invalid;
|
|
1913
|
+
}
|
|
1348
1914
|
/** The catalog faces the dropdowns classify against; undefined while unready. */
|
|
1349
1915
|
function catalogOf(state) {
|
|
1350
1916
|
return state.catalogStatus === "ready" ? {
|
|
@@ -1533,24 +2099,79 @@ window.__ModuleLoader__.load({
|
|
|
1533
2099
|
if (snapshot.switchesStatus === "idle") controller.loadSwitches();
|
|
1534
2100
|
}, [controller]);
|
|
1535
2101
|
const [scalars, setScalars] = (0, react.useState)(() => scalarsOf(defaultFallbacksConfig));
|
|
1536
|
-
const [
|
|
2102
|
+
const [allDayModel, setAllDayModel] = (0, react.useState)(() => allDayModelOf(defaultFallbacksConfig.rootChain));
|
|
2103
|
+
const [allDayChainRow, setAllDayChainRow] = (0, react.useState)(() => allDayChainRowOf(defaultFallbacksConfig.rootChain, void 0));
|
|
2104
|
+
const [timeSlotRows, setTimeSlotRows] = (0, react.useState)(() => timeSlotsToRows(defaultFallbacksConfig.timeSlots ?? []));
|
|
1537
2105
|
const [roleRows, setRoleRows] = (0, react.useState)(() => rolesToRows(defaultFallbacksConfig.roles.list));
|
|
1538
2106
|
const [ruleRows, setRuleRows] = (0, react.useState)(() => rulesToRows(defaultFallbacksConfig.roles.rules));
|
|
1539
|
-
const [
|
|
2107
|
+
const [presetToAdd, setPresetToAdd] = (0, react.useState)("");
|
|
2108
|
+
const [validationErrors, setValidationErrors] = (0, react.useState)(emptyValidationErrors);
|
|
1540
2109
|
const [validationAttempted, setValidationAttempted] = (0, react.useState)(false);
|
|
2110
|
+
const [lastSaveSection, setLastSaveSection] = (0, react.useState)(null);
|
|
1541
2111
|
const seededConfigKey = (0, react.useRef)(null);
|
|
2112
|
+
const draft = assembleConfig(scalars, allDayModel, state.config.rootChain, allDayChainRow, roleRows, ruleRows, state.config.roles.list, state.config.presets, scalars.roleAutoMatch, timeSlotRows);
|
|
2113
|
+
const hasEmptyRuleRows = ruleRows.some((row) => row.role === "");
|
|
2114
|
+
const enabledDirty = scalars.enabled !== state.config.enabled;
|
|
2115
|
+
const mainDirty = enabledDirty || JSON.stringify([...draft.rootChain, draft.timeSlots]) !== JSON.stringify([...state.config.rootChain, state.config.timeSlots ?? []]);
|
|
2116
|
+
const subDirty = hasEmptyRuleRows || JSON.stringify(draft.roles) !== JSON.stringify(state.config.roles);
|
|
2117
|
+
const advancedDirty = JSON.stringify([
|
|
2118
|
+
draft.triggerCodes,
|
|
2119
|
+
draft.cooldownMs,
|
|
2120
|
+
draft.revertPolicy,
|
|
2121
|
+
draft.maxSwitchesPerStep,
|
|
2122
|
+
draft.alwaysModeRetryCap,
|
|
2123
|
+
draft.roleAutoMatch
|
|
2124
|
+
]) !== JSON.stringify([
|
|
2125
|
+
state.config.triggerCodes,
|
|
2126
|
+
state.config.cooldownMs,
|
|
2127
|
+
state.config.revertPolicy,
|
|
2128
|
+
state.config.maxSwitchesPerStep,
|
|
2129
|
+
state.config.alwaysModeRetryCap,
|
|
2130
|
+
state.config.roleAutoMatch
|
|
2131
|
+
]);
|
|
2132
|
+
const dirty = mainDirty || subDirty || advancedDirty;
|
|
2133
|
+
const firstSeedDone = (0, react.useRef)(false);
|
|
2134
|
+
const forceReseed = (0, react.useRef)(false);
|
|
1542
2135
|
(0, react.useEffect)(() => {
|
|
1543
2136
|
if (state.status !== "ready") return;
|
|
1544
2137
|
const key = JSON.stringify(state.config);
|
|
1545
2138
|
if (seededConfigKey.current === key) return;
|
|
1546
2139
|
seededConfigKey.current = key;
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
2140
|
+
const firstSeed = !firstSeedDone.current;
|
|
2141
|
+
firstSeedDone.current = true;
|
|
2142
|
+
const force = forceReseed.current;
|
|
2143
|
+
forceReseed.current = false;
|
|
2144
|
+
const catalog = catalogOf(state);
|
|
2145
|
+
if (firstSeed || force || !mainDirty) {
|
|
2146
|
+
setAllDayModel(allDayModelOf(state.config.rootChain));
|
|
2147
|
+
setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalog));
|
|
2148
|
+
setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalog));
|
|
2149
|
+
setScalars((prev) => ({
|
|
2150
|
+
...prev,
|
|
2151
|
+
enabled: state.config.enabled,
|
|
2152
|
+
tz: state.config.tz ?? "Asia/Shanghai"
|
|
2153
|
+
}));
|
|
2154
|
+
}
|
|
2155
|
+
if (firstSeed || force || !subDirty) {
|
|
2156
|
+
setRoleRows(rolesToRows(state.config.roles.list, catalog));
|
|
2157
|
+
setRuleRows(rulesToRows(state.config.roles.rules, catalog));
|
|
2158
|
+
}
|
|
2159
|
+
if (firstSeed || force || !advancedDirty) setScalars((prev) => ({
|
|
2160
|
+
...prev,
|
|
2161
|
+
triggerCodes: [...state.config.triggerCodes],
|
|
2162
|
+
cooldownMs: state.config.cooldownMs,
|
|
2163
|
+
revertPolicy: state.config.revertPolicy,
|
|
2164
|
+
maxSwitchesPerStep: state.config.maxSwitchesPerStep,
|
|
2165
|
+
alwaysModeRetryCap: state.config.alwaysModeRetryCap,
|
|
2166
|
+
roleAutoMatch: state.config.roleAutoMatch
|
|
2167
|
+
}));
|
|
2168
|
+
}, [
|
|
2169
|
+
state.status,
|
|
2170
|
+
state.config,
|
|
2171
|
+
mainDirty,
|
|
2172
|
+
subDirty,
|
|
2173
|
+
advancedDirty
|
|
2174
|
+
]);
|
|
1554
2175
|
const updateScalars = (mutator) => {
|
|
1555
2176
|
setScalars((prev) => {
|
|
1556
2177
|
const next = {
|
|
@@ -1561,17 +2182,32 @@ window.__ModuleLoader__.load({
|
|
|
1561
2182
|
return next;
|
|
1562
2183
|
});
|
|
1563
2184
|
};
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1566
|
-
...row
|
|
1567
|
-
|
|
1568
|
-
...
|
|
2185
|
+
const updateTimeSlotRow = (index, patch) => {
|
|
2186
|
+
setTimeSlotRows((rows) => {
|
|
2187
|
+
const next = rows.map((row) => ({ ...row }));
|
|
2188
|
+
next[index] = {
|
|
2189
|
+
...next[index],
|
|
1569
2190
|
...patch
|
|
1570
|
-
}
|
|
1571
|
-
|
|
2191
|
+
};
|
|
2192
|
+
return next;
|
|
2193
|
+
});
|
|
2194
|
+
};
|
|
2195
|
+
const updateTimeSlotSelector = (rowIndex, selectorIndex, patch) => {
|
|
2196
|
+
setTimeSlotRows((rows) => {
|
|
2197
|
+
const next = rows.map((row) => ({
|
|
2198
|
+
...row,
|
|
2199
|
+
selectors: row.selectors.map((selector) => ({ ...selector }))
|
|
2200
|
+
}));
|
|
2201
|
+
const selectors = next[rowIndex].selectors;
|
|
2202
|
+
selectors[selectorIndex] = {
|
|
2203
|
+
...selectors[selectorIndex],
|
|
2204
|
+
...patch
|
|
2205
|
+
};
|
|
2206
|
+
return next;
|
|
2207
|
+
});
|
|
1572
2208
|
};
|
|
1573
|
-
const
|
|
1574
|
-
|
|
2209
|
+
const addTimeSlotSelector = (rowIndex) => {
|
|
2210
|
+
setTimeSlotRows((rows) => rows.map((row, index) => index === rowIndex ? {
|
|
1575
2211
|
...row,
|
|
1576
2212
|
selectors: [...row.selectors, {
|
|
1577
2213
|
wildcard: false,
|
|
@@ -1580,12 +2216,88 @@ window.__ModuleLoader__.load({
|
|
|
1580
2216
|
}]
|
|
1581
2217
|
} : row));
|
|
1582
2218
|
};
|
|
1583
|
-
const
|
|
1584
|
-
|
|
2219
|
+
const removeTimeSlotSelector = (rowIndex, selectorIndex) => {
|
|
2220
|
+
setTimeSlotRows((rows) => rows.map((row, index) => index === rowIndex ? {
|
|
1585
2221
|
...row,
|
|
1586
2222
|
selectors: row.selectors.filter((_, sIndex) => sIndex !== selectorIndex)
|
|
1587
2223
|
} : row));
|
|
1588
2224
|
};
|
|
2225
|
+
const addPresetSlotRow = () => {
|
|
2226
|
+
if (presetToAdd === "") return;
|
|
2227
|
+
if ((presetToAdd === "glm-peak" || presetToAdd === "glm-valley") && !glmConfigured) return;
|
|
2228
|
+
setTimeSlotRows((rows) => [...rows, {
|
|
2229
|
+
kind: "preset",
|
|
2230
|
+
preset: presetToAdd,
|
|
2231
|
+
start: "",
|
|
2232
|
+
end: "",
|
|
2233
|
+
days: [],
|
|
2234
|
+
name: "",
|
|
2235
|
+
collapsed: false,
|
|
2236
|
+
selectors: []
|
|
2237
|
+
}]);
|
|
2238
|
+
setPresetToAdd("");
|
|
2239
|
+
};
|
|
2240
|
+
const addCustomSlotRow = () => {
|
|
2241
|
+
setTimeSlotRows((rows) => [...rows, {
|
|
2242
|
+
kind: "custom",
|
|
2243
|
+
start: "",
|
|
2244
|
+
end: "",
|
|
2245
|
+
days: [],
|
|
2246
|
+
name: "",
|
|
2247
|
+
collapsed: false,
|
|
2248
|
+
selectors: []
|
|
2249
|
+
}]);
|
|
2250
|
+
};
|
|
2251
|
+
const removeTimeSlotRow = (index) => {
|
|
2252
|
+
setTimeSlotRows((rows) => rows.filter((_, rowIndex) => rowIndex !== index));
|
|
2253
|
+
};
|
|
2254
|
+
const moveTimeSlotRow = (index, delta) => {
|
|
2255
|
+
setTimeSlotRows((rows) => {
|
|
2256
|
+
const target = index + delta;
|
|
2257
|
+
if (target < 0 || target >= rows.length) return rows;
|
|
2258
|
+
const next = rows.map((row) => ({ ...row }));
|
|
2259
|
+
const moved = next[index];
|
|
2260
|
+
next[index] = next[target];
|
|
2261
|
+
next[target] = moved;
|
|
2262
|
+
return next;
|
|
2263
|
+
});
|
|
2264
|
+
};
|
|
2265
|
+
const [draggedSlotIndex, setDraggedSlotIndex] = (0, react.useState)(null);
|
|
2266
|
+
const [overSlotIndex, setOverSlotIndex] = (0, react.useState)(null);
|
|
2267
|
+
const reorderTimeSlotRow = (from, to) => {
|
|
2268
|
+
setTimeSlotRows((rows) => {
|
|
2269
|
+
if (from === to || from < 0 || to < 0 || from >= rows.length || to >= rows.length) return rows;
|
|
2270
|
+
const next = rows.map((row) => ({ ...row }));
|
|
2271
|
+
const [moved] = next.splice(from, 1);
|
|
2272
|
+
next.splice(to, 0, moved);
|
|
2273
|
+
return next;
|
|
2274
|
+
});
|
|
2275
|
+
};
|
|
2276
|
+
const updateAllDayChainSelector = (selectorIndex, patch) => {
|
|
2277
|
+
setAllDayChainRow((row) => ({
|
|
2278
|
+
...row,
|
|
2279
|
+
selectors: row.selectors.map((selector, index) => index === selectorIndex ? {
|
|
2280
|
+
...selector,
|
|
2281
|
+
...patch
|
|
2282
|
+
} : selector)
|
|
2283
|
+
}));
|
|
2284
|
+
};
|
|
2285
|
+
const addAllDayChainSelector = () => {
|
|
2286
|
+
setAllDayChainRow((row) => ({
|
|
2287
|
+
...row,
|
|
2288
|
+
selectors: [...row.selectors, {
|
|
2289
|
+
wildcard: false,
|
|
2290
|
+
provider: null,
|
|
2291
|
+
model: null
|
|
2292
|
+
}]
|
|
2293
|
+
}));
|
|
2294
|
+
};
|
|
2295
|
+
const removeAllDayChainSelector = (selectorIndex) => {
|
|
2296
|
+
setAllDayChainRow((row) => ({
|
|
2297
|
+
...row,
|
|
2298
|
+
selectors: row.selectors.filter((_, index) => index !== selectorIndex)
|
|
2299
|
+
}));
|
|
2300
|
+
};
|
|
1589
2301
|
const updateRoleRow = (index, patch) => {
|
|
1590
2302
|
setRoleRows((rows) => {
|
|
1591
2303
|
const next = rows.map((row) => ({ ...row }));
|
|
@@ -1631,7 +2343,8 @@ window.__ModuleLoader__.load({
|
|
|
1631
2343
|
id: "",
|
|
1632
2344
|
persona: "",
|
|
1633
2345
|
selectors: [],
|
|
1634
|
-
fallback: "inherit-root"
|
|
2346
|
+
fallback: "inherit-root",
|
|
2347
|
+
collapsed: true
|
|
1635
2348
|
}]);
|
|
1636
2349
|
};
|
|
1637
2350
|
const removeRole = (index) => {
|
|
@@ -1647,15 +2360,21 @@ window.__ModuleLoader__.load({
|
|
|
1647
2360
|
return next;
|
|
1648
2361
|
});
|
|
1649
2362
|
};
|
|
1650
|
-
const
|
|
1651
|
-
|
|
1652
|
-
|
|
2363
|
+
const allValidationErrors = [
|
|
2364
|
+
...validationErrors.main,
|
|
2365
|
+
...validationErrors.sub,
|
|
2366
|
+
...validationErrors.advanced
|
|
2367
|
+
];
|
|
1653
2368
|
const saving = state.status === "saving";
|
|
1654
2369
|
const writable = state.writable;
|
|
1655
2370
|
const unknownCodes = scalars.triggerCodes.filter((code) => !KNOWN_TRIGGER_CODES.includes(code));
|
|
1656
|
-
const
|
|
2371
|
+
const presetsPresent = timeSlotRows.some((row) => row.kind === "preset");
|
|
2372
|
+
const glmConfigured = state.configuredProviders.some((entry) => entry.provider === "zai-coding-cn");
|
|
2373
|
+
const slotState = resolveSlotState(state.config, /* @__PURE__ */ new Date(), scalars.tz);
|
|
2374
|
+
const activeSlotIndex = slotState.winner === "all-day" ? -1 : state.config.timeSlots?.indexOf(slotState.winner) ?? -1;
|
|
1657
2375
|
const roleOptions = ruleRoleOptions({ list: roleRows });
|
|
1658
2376
|
const invalidRoleIds = validationAttempted ? collectInvalidRoleIds(roleRows) : null;
|
|
2377
|
+
const invalidSlotRows = validationAttempted ? collectInvalidSlotRows(timeSlotRows) : null;
|
|
1659
2378
|
const seededIds = /* @__PURE__ */ new Map();
|
|
1660
2379
|
for (const seed of state.seeds) seededIds.set(seed.id.trim(), seed.overridden);
|
|
1661
2380
|
const latestSwitch = state.switches[0];
|
|
@@ -1674,45 +2393,129 @@ window.__ModuleLoader__.load({
|
|
|
1674
2393
|
};
|
|
1675
2394
|
switchesLine = latestSwitch.reason === "role-inject" ? t("status.switches.compact.roleInject", params) : t("status.switches.compact", params);
|
|
1676
2395
|
}
|
|
1677
|
-
const
|
|
2396
|
+
const catalogSeededSections = (0, react.useRef)({
|
|
2397
|
+
epoch: null,
|
|
2398
|
+
main: false,
|
|
2399
|
+
sub: false
|
|
2400
|
+
});
|
|
1678
2401
|
(0, react.useEffect)(() => {
|
|
1679
2402
|
if (state.catalogStatus !== "ready") return;
|
|
1680
|
-
|
|
1681
|
-
if (
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
2403
|
+
const seed = catalogSeededSections.current;
|
|
2404
|
+
if (seed.epoch !== state.catalogEpoch) {
|
|
2405
|
+
seed.epoch = state.catalogEpoch;
|
|
2406
|
+
seed.main = false;
|
|
2407
|
+
seed.sub = false;
|
|
2408
|
+
}
|
|
2409
|
+
const catalog = catalogOf(state);
|
|
2410
|
+
if (!mainDirty && !seed.main) {
|
|
2411
|
+
seed.main = true;
|
|
2412
|
+
setAllDayModel(allDayModelOf(state.config.rootChain));
|
|
2413
|
+
setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalog));
|
|
2414
|
+
setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalog));
|
|
2415
|
+
}
|
|
2416
|
+
if (!subDirty && !seed.sub) {
|
|
2417
|
+
seed.sub = true;
|
|
2418
|
+
setRoleRows(rolesToRows(state.config.roles.list, catalog));
|
|
2419
|
+
setRuleRows(rulesToRows(state.config.roles.rules, catalog));
|
|
2420
|
+
}
|
|
1686
2421
|
}, [
|
|
1687
2422
|
state.catalogStatus,
|
|
1688
2423
|
state.catalogEpoch,
|
|
1689
2424
|
state.config,
|
|
1690
|
-
|
|
2425
|
+
mainDirty,
|
|
2426
|
+
subDirty
|
|
1691
2427
|
]);
|
|
1692
|
-
const
|
|
2428
|
+
const sectionPatch = (section) => {
|
|
2429
|
+
const base = {
|
|
2430
|
+
...state.config,
|
|
2431
|
+
enabled: scalars.enabled
|
|
2432
|
+
};
|
|
2433
|
+
switch (section) {
|
|
2434
|
+
case "main": return {
|
|
2435
|
+
...base,
|
|
2436
|
+
rootChain: draft.rootChain,
|
|
2437
|
+
timeSlots: draft.timeSlots,
|
|
2438
|
+
tz: draft.tz
|
|
2439
|
+
};
|
|
2440
|
+
case "sub": return {
|
|
2441
|
+
...base,
|
|
2442
|
+
roles: draft.roles
|
|
2443
|
+
};
|
|
2444
|
+
case "advanced": return {
|
|
2445
|
+
...base,
|
|
2446
|
+
triggerCodes: draft.triggerCodes,
|
|
2447
|
+
cooldownMs: draft.cooldownMs,
|
|
2448
|
+
revertPolicy: draft.revertPolicy,
|
|
2449
|
+
maxSwitchesPerStep: draft.maxSwitchesPerStep,
|
|
2450
|
+
alwaysModeRetryCap: draft.alwaysModeRetryCap,
|
|
2451
|
+
roleAutoMatch: draft.roleAutoMatch
|
|
2452
|
+
};
|
|
2453
|
+
}
|
|
2454
|
+
};
|
|
2455
|
+
const save = (section) => {
|
|
2456
|
+
setLastSaveSection(section);
|
|
1693
2457
|
const errors = validateDraft(draft, t, seededIds);
|
|
1694
|
-
if (hasEmptyRuleRows) errors.push(t("validation.ruleRoleRequired"));
|
|
1695
|
-
if (errors.length > 0) {
|
|
2458
|
+
if (section === "sub" && hasEmptyRuleRows) errors.sub.push(t("validation.ruleRoleRequired"));
|
|
2459
|
+
if (errors[section].length > 0) {
|
|
1696
2460
|
setValidationErrors(errors);
|
|
1697
2461
|
setValidationAttempted(true);
|
|
1698
2462
|
return;
|
|
1699
2463
|
}
|
|
1700
|
-
setValidationErrors(
|
|
2464
|
+
setValidationErrors(emptyValidationErrors());
|
|
2465
|
+
setValidationAttempted(false);
|
|
2466
|
+
controller.save(sectionPatch(section));
|
|
2467
|
+
};
|
|
2468
|
+
const saveEnabled = () => {
|
|
2469
|
+
setLastSaveSection("main");
|
|
2470
|
+
setValidationErrors(emptyValidationErrors());
|
|
2471
|
+
setValidationAttempted(false);
|
|
2472
|
+
controller.save({
|
|
2473
|
+
...state.config,
|
|
2474
|
+
enabled: scalars.enabled
|
|
2475
|
+
});
|
|
2476
|
+
};
|
|
2477
|
+
const discardSection = (section) => {
|
|
2478
|
+
switch (section) {
|
|
2479
|
+
case "main":
|
|
2480
|
+
setAllDayModel(allDayModelOf(state.config.rootChain));
|
|
2481
|
+
setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalogOf(state)));
|
|
2482
|
+
setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalogOf(state)));
|
|
2483
|
+
setScalars((prev) => ({
|
|
2484
|
+
...prev,
|
|
2485
|
+
enabled: state.config.enabled,
|
|
2486
|
+
tz: state.config.tz ?? "Asia/Shanghai"
|
|
2487
|
+
}));
|
|
2488
|
+
break;
|
|
2489
|
+
case "sub":
|
|
2490
|
+
setRoleRows(rolesToRows(state.config.roles.list, catalogOf(state)));
|
|
2491
|
+
setRuleRows(rulesToRows(state.config.roles.rules, catalogOf(state)));
|
|
2492
|
+
break;
|
|
2493
|
+
case "advanced": setScalars((prev) => ({
|
|
2494
|
+
...prev,
|
|
2495
|
+
triggerCodes: [...state.config.triggerCodes],
|
|
2496
|
+
cooldownMs: state.config.cooldownMs,
|
|
2497
|
+
revertPolicy: state.config.revertPolicy,
|
|
2498
|
+
maxSwitchesPerStep: state.config.maxSwitchesPerStep,
|
|
2499
|
+
alwaysModeRetryCap: state.config.alwaysModeRetryCap,
|
|
2500
|
+
roleAutoMatch: state.config.roleAutoMatch
|
|
2501
|
+
}));
|
|
2502
|
+
}
|
|
2503
|
+
setValidationErrors(emptyValidationErrors());
|
|
1701
2504
|
setValidationAttempted(false);
|
|
1702
|
-
controller.save(draft);
|
|
1703
2505
|
};
|
|
1704
|
-
const
|
|
1705
|
-
setScalars(
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
setValidationErrors(
|
|
2506
|
+
const discardEnabled = () => {
|
|
2507
|
+
setScalars((prev) => ({
|
|
2508
|
+
...prev,
|
|
2509
|
+
enabled: state.config.enabled
|
|
2510
|
+
}));
|
|
2511
|
+
setValidationErrors(emptyValidationErrors());
|
|
1710
2512
|
setValidationAttempted(false);
|
|
1711
2513
|
};
|
|
1712
2514
|
(0, react.useEffect)(() => {
|
|
1713
2515
|
if (!validationAttempted) return;
|
|
1714
|
-
|
|
1715
|
-
|
|
2516
|
+
const errors = validateDraft(draft, t, seededIds);
|
|
2517
|
+
if (errors.main.length === 0 && errors.sub.length === 0 && errors.advanced.length === 0 && !ruleRows.some((row) => row.role === "")) {
|
|
2518
|
+
setValidationErrors(emptyValidationErrors());
|
|
1716
2519
|
setValidationAttempted(false);
|
|
1717
2520
|
}
|
|
1718
2521
|
}, [
|
|
@@ -1721,13 +2524,10 @@ window.__ModuleLoader__.load({
|
|
|
1721
2524
|
ruleRows,
|
|
1722
2525
|
t
|
|
1723
2526
|
]);
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
setConfirmingReset(false);
|
|
1729
|
-
});
|
|
1730
|
-
};
|
|
2527
|
+
(0, react.useEffect)(() => {
|
|
2528
|
+
if (state.status === "ready") setLastSaveSection(null);
|
|
2529
|
+
if (state.status === "error") forceReseed.current = false;
|
|
2530
|
+
}, [state.status]);
|
|
1731
2531
|
const [userOpen, setUserOpen] = (0, react.useState)(false);
|
|
1732
2532
|
const [advancedOpen, setAdvancedOpen] = (0, react.useState)(false);
|
|
1733
2533
|
const degradedLatch = (0, react.useRef)(false);
|
|
@@ -1768,871 +2568,1323 @@ window.__ModuleLoader__.load({
|
|
|
1768
2568
|
});
|
|
1769
2569
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
1770
2570
|
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", {
|
|
2571
|
+
children: [header, open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2572
|
+
className: FallbacksCard_module_css_default.body,
|
|
2573
|
+
children: [
|
|
2574
|
+
state.legacyKeys.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2575
|
+
className: FallbacksCard_module_css_default.legacyNotice,
|
|
2576
|
+
role: "status",
|
|
2577
|
+
children: t("legacy.banner", { keys: state.legacyKeys.join(", ") })
|
|
2578
|
+
}),
|
|
2579
|
+
state.status === "error" && state.error !== null && lastSaveSection === null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2580
|
+
className: FallbacksCard_module_css_default.noticeRow,
|
|
2581
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1797
2582
|
className: FallbacksCard_module_css_default.error,
|
|
1798
2583
|
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
|
-
|
|
2584
|
+
children: t("error.generic", { message: state.error })
|
|
2585
|
+
}), !state.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2586
|
+
variant: "outline",
|
|
2587
|
+
size: "sm",
|
|
2588
|
+
onClick: () => {
|
|
2589
|
+
controller.load();
|
|
2590
|
+
},
|
|
2591
|
+
children: t("retry")
|
|
2592
|
+
})]
|
|
2593
|
+
}),
|
|
2594
|
+
degraded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2595
|
+
className: FallbacksCard_module_css_default.notice,
|
|
2596
|
+
role: "status",
|
|
2597
|
+
children: t("unavailable")
|
|
2598
|
+
}),
|
|
2599
|
+
state.status === "ready" && !state.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2600
|
+
className: FallbacksCard_module_css_default.readOnly,
|
|
2601
|
+
role: "status",
|
|
2602
|
+
children: t("readOnly")
|
|
2603
|
+
}),
|
|
2604
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2605
|
+
className: FallbacksCard_module_css_default.form,
|
|
2606
|
+
children: [
|
|
2607
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2608
|
+
className: FallbacksCard_module_css_default.checkboxRow,
|
|
2609
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2610
|
+
className: FallbacksCard_module_css_default.checkLabel,
|
|
2611
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2612
|
+
className: FallbacksCard_module_css_default.checkLabelTitle,
|
|
2613
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
2614
|
+
htmlFor: "fallbacks-enabled",
|
|
2615
|
+
children: t("enabled.label")
|
|
2616
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2617
|
+
label: t("enabled.tooltip"),
|
|
2618
|
+
disabled: !writable
|
|
1830
2619
|
})]
|
|
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
|
-
}
|
|
2620
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2621
|
+
className: FallbacksCard_module_css_default.checkLabelDesc,
|
|
2622
|
+
children: t("enabled.hint")
|
|
1842
2623
|
})]
|
|
1843
|
-
}),
|
|
1844
|
-
|
|
2624
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2625
|
+
id: "fallbacks-enabled",
|
|
2626
|
+
type: "checkbox",
|
|
2627
|
+
className: FallbacksCard_module_css_default.checkbox,
|
|
2628
|
+
checked: scalars.enabled,
|
|
2629
|
+
disabled: !writable,
|
|
2630
|
+
onChange: (event) => {
|
|
2631
|
+
updateScalars((draft) => {
|
|
2632
|
+
draft.enabled = event.target.checked;
|
|
2633
|
+
});
|
|
2634
|
+
}
|
|
2635
|
+
})]
|
|
2636
|
+
}),
|
|
2637
|
+
!scalars.enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2638
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1845
2639
|
className: FallbacksCard_module_css_default.offNotice,
|
|
1846
2640
|
children: t("enabled.off")
|
|
1847
2641
|
}),
|
|
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
|
-
|
|
2642
|
+
allValidationErrors.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2643
|
+
className: FallbacksCard_module_css_default.error,
|
|
2644
|
+
role: "alert",
|
|
2645
|
+
children: `${t("validation.blocked")}${allValidationErrors.join("; ")}`
|
|
2646
|
+
}),
|
|
2647
|
+
lastSaveSection === "main" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2648
|
+
className: FallbacksCard_module_css_default.error,
|
|
2649
|
+
role: "alert",
|
|
2650
|
+
children: t("error.generic", { message: state.error })
|
|
2651
|
+
}),
|
|
2652
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2653
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
2654
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2655
|
+
type: "button",
|
|
2656
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2657
|
+
disabled: !enabledDirty || saving,
|
|
2658
|
+
onClick: discardEnabled,
|
|
2659
|
+
children: t("discard")
|
|
2660
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2661
|
+
type: "button",
|
|
2662
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2663
|
+
disabled: !writable || saving || !enabledDirty,
|
|
2664
|
+
onClick: saveEnabled,
|
|
2665
|
+
children: saving ? t("save.saving") : t("save")
|
|
2666
|
+
})]
|
|
2667
|
+
})
|
|
2668
|
+
] }),
|
|
2669
|
+
scalars.enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
2670
|
+
className: FallbacksCard_module_css_default.fieldset,
|
|
2671
|
+
disabled: !writable,
|
|
2672
|
+
children: [
|
|
2673
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2674
|
+
className: FallbacksCard_module_css_default.sectionHeading,
|
|
2675
|
+
id: "fallbacks-main-agent",
|
|
2676
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2677
|
+
className: FallbacksCard_module_css_default.sectionHeadingText,
|
|
2678
|
+
children: t("mainAgent.label")
|
|
2679
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2680
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
2681
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2682
|
+
type: "button",
|
|
2683
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2684
|
+
disabled: !mainDirty || saving,
|
|
2685
|
+
onClick: () => {
|
|
2686
|
+
discardSection("main");
|
|
2687
|
+
},
|
|
2688
|
+
children: t("discard")
|
|
2689
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2690
|
+
type: "button",
|
|
2691
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
2692
|
+
disabled: !writable || saving || !mainDirty,
|
|
2693
|
+
onClick: () => {
|
|
2694
|
+
save("main");
|
|
2695
|
+
},
|
|
2696
|
+
children: saving ? t("save.saving") : t("save")
|
|
2697
|
+
})]
|
|
2698
|
+
})]
|
|
2699
|
+
}),
|
|
2700
|
+
validationErrors.main.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2701
|
+
className: FallbacksCard_module_css_default.error,
|
|
2702
|
+
role: "alert",
|
|
2703
|
+
children: `${t("validation.blocked")}${validationErrors.main.join("; ")}`
|
|
2704
|
+
}),
|
|
2705
|
+
lastSaveSection === "main" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2706
|
+
className: FallbacksCard_module_css_default.error,
|
|
2707
|
+
role: "alert",
|
|
2708
|
+
children: t("error.generic", { message: state.error })
|
|
2709
|
+
}),
|
|
2710
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2711
|
+
className: FallbacksCard_module_css_default.field,
|
|
2712
|
+
role: "group",
|
|
2713
|
+
"aria-labelledby": "fallbacks-time-slots",
|
|
2714
|
+
children: [
|
|
2715
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2716
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
2717
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2718
|
+
id: "fallbacks-time-slots",
|
|
2719
|
+
children: t("timeSlots.label")
|
|
2720
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
2721
|
+
label: t("timeSlots.tooltip"),
|
|
2722
|
+
disabled: !writable
|
|
2723
|
+
})]
|
|
2724
|
+
}),
|
|
2725
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2726
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2727
|
+
children: t("timeSlots.hint")
|
|
2728
|
+
}),
|
|
2729
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2730
|
+
className: FallbacksCard_module_css_default.list,
|
|
2731
|
+
children: timeSlotRows.map((row, index) => {
|
|
2732
|
+
const invalidWindow = invalidSlotRows?.has(index) ?? false;
|
|
2733
|
+
const chainEmpty = row.selectors.every((selector) => selectorRowToRaw(selector) === "");
|
|
2734
|
+
const firstModel = row.selectors.map(selectorRowToRaw).find((entry) => entry !== "");
|
|
2735
|
+
const slotExpanded = !row.collapsed || !writable;
|
|
2736
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2737
|
+
className: `${FallbacksCard_module_css_default.editorCard} ${draggedSlotIndex === index ? FallbacksCard_module_css_default.slotCardDragging : ""} ${overSlotIndex === index && draggedSlotIndex !== null && draggedSlotIndex !== index ? FallbacksCard_module_css_default.slotCardOver : ""}`,
|
|
2738
|
+
onDragOver: (event) => {
|
|
2739
|
+
if (draggedSlotIndex === null) return;
|
|
2740
|
+
event.preventDefault();
|
|
2741
|
+
if (overSlotIndex !== index) setOverSlotIndex(index);
|
|
2742
|
+
},
|
|
2743
|
+
onDrop: (event) => {
|
|
2744
|
+
event.preventDefault();
|
|
2745
|
+
const from = draggedSlotIndex;
|
|
2746
|
+
setDraggedSlotIndex(null);
|
|
2747
|
+
setOverSlotIndex(null);
|
|
2748
|
+
if (from !== null && from !== index) reorderTimeSlotRow(from, index);
|
|
2749
|
+
},
|
|
2750
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2751
|
+
className: FallbacksCard_module_css_default.collapseRow,
|
|
2752
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2753
|
+
type: "button",
|
|
2754
|
+
className: FallbacksCard_module_css_default.collapseToggle,
|
|
2755
|
+
"aria-expanded": slotExpanded,
|
|
2756
|
+
"aria-label": t(slotExpanded ? "timeSlots.collapse" : "timeSlots.expand"),
|
|
1897
2757
|
disabled: !writable,
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
updateRootChainSelector(selectorIndex, patch);
|
|
2758
|
+
onClick: () => {
|
|
2759
|
+
updateTimeSlotRow(index, { collapsed: !row.collapsed });
|
|
1901
2760
|
},
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
children: [
|
|
1923
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1924
|
-
className: FallbacksCard_module_css_default.fieldLabel,
|
|
1925
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1926
|
-
id: "fallbacks-roles-list",
|
|
1927
|
-
children: t("roles.list.label")
|
|
1928
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
1929
|
-
label: t("roles.list.tooltip"),
|
|
1930
|
-
disabled: !writable
|
|
1931
|
-
})]
|
|
1932
|
-
}),
|
|
1933
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1934
|
-
className: FallbacksCard_module_css_default.hint,
|
|
1935
|
-
children: t("roles.list.hint")
|
|
1936
|
-
}),
|
|
1937
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1938
|
-
className: FallbacksCard_module_css_default.list,
|
|
1939
|
-
children: roleRows.map((row, index) => {
|
|
1940
|
-
const invalid = invalidRoleIds?.has(row.id.trim()) ?? false;
|
|
1941
|
-
const seed = seededIds.get(row.id.trim());
|
|
1942
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1943
|
-
className: FallbacksCard_module_css_default.editorCard,
|
|
1944
|
-
children: [
|
|
1945
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1946
|
-
className: FallbacksCard_module_css_default.ruleGrid,
|
|
1947
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1948
|
-
className: FallbacksCard_module_css_default.ruleCell,
|
|
1949
|
-
children: [
|
|
1950
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1951
|
-
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
1952
|
-
children: t("roles.id")
|
|
1953
|
-
}),
|
|
1954
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1955
|
-
className: `${FallbacksCard_module_css_default.input} ${invalid ? FallbacksCard_module_css_default.inputInvalid : ""}`,
|
|
1956
|
-
value: row.id,
|
|
1957
|
-
placeholder: t("roles.idPlaceholder"),
|
|
1958
|
-
"aria-label": t("roles.id"),
|
|
1959
|
-
"aria-invalid": invalid ? true : void 0,
|
|
1960
|
-
disabled: !writable || seed !== void 0,
|
|
1961
|
-
onChange: (event) => {
|
|
1962
|
-
updateRoleRow(index, { id: event.target.value });
|
|
1963
|
-
}
|
|
1964
|
-
}),
|
|
1965
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1966
|
-
className: FallbacksCard_module_css_default.hint,
|
|
1967
|
-
children: t("roles.id.hint")
|
|
1968
|
-
})
|
|
1969
|
-
]
|
|
2761
|
+
children: [
|
|
2762
|
+
/* @__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 }),
|
|
2763
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2764
|
+
className: FallbacksCard_module_css_default.collapseTitle,
|
|
2765
|
+
children: row.kind === "preset" ? t(`timeSlots.preset.${row.preset}.label`) : row.name !== "" ? row.name : `custom ${row.start}-${row.end}`
|
|
2766
|
+
}),
|
|
2767
|
+
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", {
|
|
2768
|
+
className: `${FallbacksCard_module_css_default.slotTag} ${FallbacksCard_module_css_default.slotTagHighCost}`,
|
|
2769
|
+
children: t("timeSlots.preset.highCost")
|
|
2770
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2771
|
+
className: `${FallbacksCard_module_css_default.slotTag} ${FallbacksCard_module_css_default.slotTagMultiplier}`,
|
|
2772
|
+
children: t("timeSlots.preset.multiplier", { n: row.preset === "liang-peak" ? "2" : "3" })
|
|
2773
|
+
})] }),
|
|
2774
|
+
activeSlotIndex === index && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2775
|
+
className: `${FallbacksCard_module_css_default.slotTag} ${FallbacksCard_module_css_default.slotTagActive}`,
|
|
2776
|
+
children: t("timeSlots.active")
|
|
2777
|
+
}),
|
|
2778
|
+
firstModel !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2779
|
+
className: FallbacksCard_module_css_default.collapseMeta,
|
|
2780
|
+
children: firstModel
|
|
1970
2781
|
})
|
|
1971
|
-
|
|
1972
|
-
|
|
2782
|
+
]
|
|
2783
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2784
|
+
type: "button",
|
|
2785
|
+
className: FallbacksCard_module_css_default.dragHandle,
|
|
2786
|
+
draggable: writable,
|
|
2787
|
+
"data-tip": t("timeSlots.drag"),
|
|
2788
|
+
"aria-label": t("timeSlots.drag"),
|
|
2789
|
+
disabled: !writable,
|
|
2790
|
+
onDragStart: () => {
|
|
2791
|
+
if (!writable) return;
|
|
2792
|
+
setDraggedSlotIndex(index);
|
|
2793
|
+
setOverSlotIndex(index);
|
|
2794
|
+
},
|
|
2795
|
+
onDragEnd: () => {
|
|
2796
|
+
setDraggedSlotIndex(null);
|
|
2797
|
+
setOverSlotIndex(null);
|
|
2798
|
+
},
|
|
2799
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { className: FallbacksCard_module_css_default.dragHandleIcon })
|
|
2800
|
+
})]
|
|
2801
|
+
}), slotExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2802
|
+
row.kind === "preset" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2803
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1973
2804
|
className: FallbacksCard_module_css_default.ruleGrid,
|
|
1974
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2805
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1975
2806
|
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
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
})
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
disabled: !writable,
|
|
2017
|
-
t,
|
|
2018
|
-
onChange: (patch) => {
|
|
2019
|
-
updateRoleSelector(index, selectorIndex, patch);
|
|
2020
|
-
},
|
|
2021
|
-
onRemove: () => {
|
|
2022
|
-
removeRoleSelector(index, selectorIndex);
|
|
2807
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2808
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2809
|
+
children: t("timeSlots.preset.name")
|
|
2810
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2811
|
+
className: FallbacksCard_module_css_default.slotPresetName,
|
|
2812
|
+
children: t(`timeSlots.preset.${row.preset}.label`)
|
|
2813
|
+
})]
|
|
2814
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2815
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
2816
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2817
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2818
|
+
children: t("timeSlots.preset.windowLabel")
|
|
2819
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2820
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2821
|
+
children: t(`timeSlots.preset.${row.preset}.window`)
|
|
2822
|
+
})]
|
|
2823
|
+
})]
|
|
2824
|
+
}),
|
|
2825
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2826
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2827
|
+
children: t("timeSlots.preset.chainsOnly")
|
|
2828
|
+
}),
|
|
2829
|
+
(row.preset === "glm-peak" || row.preset === "glm-valley") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2830
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2831
|
+
children: t("timeSlots.preset.glm.note")
|
|
2832
|
+
})
|
|
2833
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2834
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2835
|
+
className: FallbacksCard_module_css_default.field,
|
|
2836
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2837
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2838
|
+
children: t("timeSlots.name")
|
|
2839
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2840
|
+
className: FallbacksCard_module_css_default.input,
|
|
2841
|
+
value: row.name,
|
|
2842
|
+
placeholder: t("timeSlots.name"),
|
|
2843
|
+
"aria-label": t("timeSlots.name"),
|
|
2844
|
+
disabled: !writable,
|
|
2845
|
+
onChange: (event) => {
|
|
2846
|
+
updateTimeSlotRow(index, { name: event.target.value });
|
|
2023
2847
|
}
|
|
2024
|
-
}
|
|
2848
|
+
})]
|
|
2849
|
+
}),
|
|
2850
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2851
|
+
className: FallbacksCard_module_css_default.field,
|
|
2852
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2853
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2854
|
+
children: t("timeSlots.tz.label")
|
|
2855
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2025
2856
|
className: FallbacksCard_module_css_default.hint,
|
|
2026
|
-
|
|
2857
|
+
"aria-label": t("timeSlots.tz.label"),
|
|
2858
|
+
children: tzDisplayLabel(presetsPresent ? "Asia/Shanghai" : hostTimeZone())
|
|
2027
2859
|
})]
|
|
2028
2860
|
}),
|
|
2029
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2861
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2030
2862
|
className: FallbacksCard_module_css_default.ruleGrid,
|
|
2031
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
2863
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2032
2864
|
className: FallbacksCard_module_css_default.ruleCell,
|
|
2033
2865
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2034
2866
|
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
|
-
|
|
2867
|
+
children: t("timeSlots.start")
|
|
2868
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2869
|
+
className: `${FallbacksCard_module_css_default.input} ${invalidWindow ? FallbacksCard_module_css_default.inputInvalid : ""}`,
|
|
2870
|
+
value: row.start,
|
|
2871
|
+
placeholder: "09:00",
|
|
2872
|
+
"aria-label": t("timeSlots.start"),
|
|
2040
2873
|
disabled: !writable,
|
|
2041
2874
|
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
|
-
})]
|
|
2875
|
+
updateTimeSlotRow(index, { start: event.target.value });
|
|
2876
|
+
}
|
|
2051
2877
|
})]
|
|
2052
|
-
})
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2878
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2879
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
2880
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2881
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2882
|
+
children: t("timeSlots.end")
|
|
2883
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2884
|
+
className: `${FallbacksCard_module_css_default.input} ${invalidWindow ? FallbacksCard_module_css_default.inputInvalid : ""}`,
|
|
2885
|
+
value: row.end,
|
|
2886
|
+
placeholder: "18:00",
|
|
2887
|
+
"aria-label": t("timeSlots.end"),
|
|
2888
|
+
disabled: !writable,
|
|
2889
|
+
onChange: (event) => {
|
|
2890
|
+
updateTimeSlotRow(index, { end: event.target.value });
|
|
2891
|
+
}
|
|
2892
|
+
})]
|
|
2893
|
+
})]
|
|
2063
2894
|
}),
|
|
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
2895
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2136
|
-
className: FallbacksCard_module_css_default.
|
|
2896
|
+
className: FallbacksCard_module_css_default.field,
|
|
2137
2897
|
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
|
-
})]
|
|
2898
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2899
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
2900
|
+
children: t("timeSlots.days")
|
|
2199
2901
|
}),
|
|
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
|
-
})]
|
|
2902
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2903
|
+
className: FallbacksCard_module_css_default.dayRow,
|
|
2904
|
+
children: SLOT_WEEKDAYS.map((day, dayIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2905
|
+
className: FallbacksCard_module_css_default.dayCell,
|
|
2906
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2907
|
+
type: "checkbox",
|
|
2908
|
+
checked: row.days.includes(dayIndex),
|
|
2909
|
+
disabled: !writable,
|
|
2910
|
+
onChange: () => {
|
|
2911
|
+
updateTimeSlotRow(index, { days: row.days.includes(dayIndex) ? row.days.filter((existing) => existing !== dayIndex) : [...row.days, dayIndex] });
|
|
2912
|
+
}
|
|
2913
|
+
}), t(`timeSlots.day.${day}`)]
|
|
2914
|
+
}, day))
|
|
2226
2915
|
}),
|
|
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
|
-
})]
|
|
2916
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2917
|
+
className: FallbacksCard_module_css_default.hint,
|
|
2918
|
+
children: t("timeSlots.days.hint")
|
|
2254
2919
|
})
|
|
2255
2920
|
]
|
|
2256
2921
|
}),
|
|
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", {
|
|
2922
|
+
(row.start !== "" || row.end !== "") && !(HHMM_RE.test(row.start) && HHMM_RE.test(row.end)) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2265
2923
|
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
|
-
})
|
|
2924
|
+
children: t("validation.slotWindow")
|
|
2280
2925
|
})
|
|
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", {
|
|
2926
|
+
] }),
|
|
2927
|
+
chainEmpty && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2370
2928
|
className: FallbacksCard_module_css_default.hint,
|
|
2371
|
-
children: t("
|
|
2929
|
+
children: t("validation.slotChainRequired")
|
|
2372
2930
|
}),
|
|
2373
|
-
|
|
2374
|
-
className: FallbacksCard_module_css_default.
|
|
2375
|
-
children:
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2931
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2932
|
+
className: FallbacksCard_module_css_default.chainSelectors,
|
|
2933
|
+
children: row.selectors.map((selector, selectorIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChainSelectorEditor, {
|
|
2934
|
+
selector,
|
|
2935
|
+
catalog: catalogOf(state),
|
|
2936
|
+
configuredProviders: state.configuredProviders,
|
|
2937
|
+
disabled: !writable,
|
|
2938
|
+
t,
|
|
2939
|
+
onChange: (patch) => {
|
|
2940
|
+
updateTimeSlotSelector(index, selectorIndex, patch);
|
|
2941
|
+
},
|
|
2942
|
+
onRemove: () => {
|
|
2943
|
+
removeTimeSlotSelector(index, selectorIndex);
|
|
2382
2944
|
}
|
|
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
|
-
})]
|
|
2945
|
+
}, selectorIndex))
|
|
2405
2946
|
}),
|
|
2406
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2407
|
-
|
|
2408
|
-
|
|
2947
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
2948
|
+
variant: "outline",
|
|
2949
|
+
size: "sm",
|
|
2950
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
2951
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
2952
|
+
onClick: () => {
|
|
2953
|
+
addTimeSlotSelector(index);
|
|
2954
|
+
},
|
|
2955
|
+
children: t("timeSlots.selector.add")
|
|
2409
2956
|
}),
|
|
2410
|
-
|
|
2411
|
-
className: FallbacksCard_module_css_default.
|
|
2412
|
-
children:
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2957
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2958
|
+
className: FallbacksCard_module_css_default.cardFoot,
|
|
2959
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2960
|
+
className: FallbacksCard_module_css_default.rowActions,
|
|
2961
|
+
children: [
|
|
2962
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2963
|
+
type: "button",
|
|
2964
|
+
className: FallbacksCard_module_css_default.iconButton,
|
|
2965
|
+
"data-tip": t("timeSlots.moveUp"),
|
|
2966
|
+
"aria-label": t("timeSlots.moveUp"),
|
|
2967
|
+
disabled: !writable || index === 0,
|
|
2968
|
+
onClick: () => {
|
|
2969
|
+
moveTimeSlotRow(index, -1);
|
|
2970
|
+
},
|
|
2971
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, {})
|
|
2972
|
+
}),
|
|
2973
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2974
|
+
type: "button",
|
|
2975
|
+
className: FallbacksCard_module_css_default.iconButton,
|
|
2976
|
+
"data-tip": t("timeSlots.moveDown"),
|
|
2977
|
+
"aria-label": t("timeSlots.moveDown"),
|
|
2978
|
+
disabled: !writable || index === timeSlotRows.length - 1,
|
|
2979
|
+
onClick: () => {
|
|
2980
|
+
moveTimeSlotRow(index, 1);
|
|
2981
|
+
},
|
|
2982
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})
|
|
2983
|
+
}),
|
|
2984
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2985
|
+
type: "button",
|
|
2986
|
+
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
2987
|
+
"data-tip": t("timeSlots.remove"),
|
|
2988
|
+
"aria-label": t("timeSlots.remove"),
|
|
2989
|
+
onClick: () => {
|
|
2990
|
+
removeTimeSlotRow(index);
|
|
2991
|
+
},
|
|
2992
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
2993
|
+
})
|
|
2994
|
+
]
|
|
2995
|
+
})
|
|
2996
|
+
})
|
|
2997
|
+
] })]
|
|
2998
|
+
}, index);
|
|
2999
|
+
})
|
|
3000
|
+
}),
|
|
3001
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3002
|
+
className: FallbacksCard_module_css_default.slotAddRow,
|
|
3003
|
+
children: [
|
|
3004
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3005
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3006
|
+
value: presetToAdd,
|
|
3007
|
+
"aria-label": t("timeSlots.presetPlaceholder"),
|
|
3008
|
+
disabled: !writable,
|
|
3009
|
+
onChange: (event) => {
|
|
3010
|
+
setPresetToAdd(event.target.value);
|
|
3011
|
+
},
|
|
3012
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3013
|
+
value: "",
|
|
3014
|
+
children: t("timeSlots.presetPlaceholder")
|
|
3015
|
+
}), SLOT_PRESET_IDS.filter((id) => !timeSlotRows.some((row) => row.kind === "preset" && row.preset === id)).map((id) => {
|
|
3016
|
+
const glmUnconfigured = !glmConfigured && (id === "glm-peak" || id === "glm-valley");
|
|
3017
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
3018
|
+
value: id,
|
|
3019
|
+
disabled: glmUnconfigured,
|
|
3020
|
+
children: [t(`timeSlots.preset.${id}.label`), glmUnconfigured ? t("timeSlots.preset.glm.unconfigured") : null]
|
|
3021
|
+
}, id);
|
|
3022
|
+
})]
|
|
2424
3023
|
}),
|
|
2425
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
3024
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3025
|
+
variant: "outline",
|
|
3026
|
+
size: "sm",
|
|
3027
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3028
|
+
disabled: !writable || presetToAdd === "",
|
|
3029
|
+
onClick: addPresetSlotRow,
|
|
3030
|
+
children: t("timeSlots.addPreset")
|
|
3031
|
+
}),
|
|
3032
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3033
|
+
variant: "outline",
|
|
3034
|
+
size: "sm",
|
|
3035
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3036
|
+
disabled: !writable,
|
|
3037
|
+
onClick: addCustomSlotRow,
|
|
3038
|
+
children: t("timeSlots.addCustom")
|
|
3039
|
+
})
|
|
3040
|
+
]
|
|
3041
|
+
})
|
|
3042
|
+
]
|
|
3043
|
+
}),
|
|
3044
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3045
|
+
className: FallbacksCard_module_css_default.field,
|
|
3046
|
+
role: "group",
|
|
3047
|
+
"aria-labelledby": "fallbacks-root-chain",
|
|
3048
|
+
children: [
|
|
3049
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3050
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3051
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3052
|
+
id: "fallbacks-root-chain",
|
|
3053
|
+
children: t("rootChain.label")
|
|
3054
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3055
|
+
label: t("rootChain.tooltip"),
|
|
3056
|
+
disabled: !writable
|
|
3057
|
+
})]
|
|
3058
|
+
}),
|
|
3059
|
+
state.catalogStatus === "error" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3060
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3061
|
+
children: t("catalog.error", { message: state.catalogError })
|
|
3062
|
+
}),
|
|
3063
|
+
state.catalogStatus === "ready" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3064
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3065
|
+
children: t("catalog.partial", { message: state.catalogError })
|
|
3066
|
+
}),
|
|
3067
|
+
state.catalogStatus === "ready" && (state.groups.length === 0 || state.configuredProviders.length === 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3068
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3069
|
+
children: t("catalog.empty")
|
|
3070
|
+
}),
|
|
3071
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3072
|
+
className: FallbacksCard_module_css_default.list,
|
|
3073
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3074
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3075
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3076
|
+
className: FallbacksCard_module_css_default.chainSelectors,
|
|
3077
|
+
children: allDayChainRow.selectors.map((selector, selectorIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChainSelectorEditor, {
|
|
3078
|
+
selector,
|
|
3079
|
+
catalog: catalogOf(state),
|
|
3080
|
+
configuredProviders: state.configuredProviders,
|
|
3081
|
+
disabled: !writable,
|
|
3082
|
+
t,
|
|
3083
|
+
onChange: (patch) => {
|
|
3084
|
+
updateAllDayChainSelector(selectorIndex, patch);
|
|
3085
|
+
},
|
|
3086
|
+
onRemove: () => {
|
|
3087
|
+
removeAllDayChainSelector(selectorIndex);
|
|
3088
|
+
}
|
|
3089
|
+
}, selectorIndex))
|
|
3090
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3091
|
+
variant: "outline",
|
|
3092
|
+
size: "sm",
|
|
3093
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3094
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3095
|
+
onClick: addAllDayChainSelector,
|
|
3096
|
+
children: t("timeSlots.selector.add")
|
|
3097
|
+
})]
|
|
3098
|
+
})
|
|
3099
|
+
})
|
|
3100
|
+
]
|
|
3101
|
+
}),
|
|
3102
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3103
|
+
className: FallbacksCard_module_css_default.field,
|
|
3104
|
+
role: "group",
|
|
3105
|
+
"aria-labelledby": "fallbacks-default-model",
|
|
3106
|
+
children: [
|
|
3107
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3108
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3109
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3110
|
+
id: "fallbacks-default-model",
|
|
3111
|
+
children: t("defaultModel.label")
|
|
3112
|
+
})
|
|
3113
|
+
}),
|
|
3114
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3115
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3116
|
+
children: t("allDay.hint")
|
|
3117
|
+
}),
|
|
3118
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3119
|
+
className: FallbacksCard_module_css_default.list,
|
|
3120
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3121
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3122
|
+
children: [
|
|
3123
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3124
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3125
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3126
|
+
type: "radio",
|
|
3127
|
+
name: "fallbacks-all-day",
|
|
3128
|
+
checked: allDayModel === ALL_DAY_FLASH,
|
|
3129
|
+
disabled: !writable,
|
|
3130
|
+
onChange: () => {
|
|
3131
|
+
setAllDayModel(ALL_DAY_FLASH);
|
|
3132
|
+
}
|
|
3133
|
+
}), t("allDay.flash")]
|
|
3134
|
+
}),
|
|
3135
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3136
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3137
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3138
|
+
type: "radio",
|
|
3139
|
+
name: "fallbacks-all-day",
|
|
3140
|
+
checked: allDayModel === ALL_DAY_PRO,
|
|
3141
|
+
disabled: !writable,
|
|
3142
|
+
onChange: () => {
|
|
3143
|
+
setAllDayModel(ALL_DAY_PRO);
|
|
3144
|
+
}
|
|
3145
|
+
}), t("allDay.pro")]
|
|
3146
|
+
}),
|
|
3147
|
+
allDayModel === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3148
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3149
|
+
children: t("allDay.nonconforming")
|
|
3150
|
+
})
|
|
3151
|
+
]
|
|
3152
|
+
})
|
|
3153
|
+
})
|
|
3154
|
+
]
|
|
3155
|
+
}),
|
|
3156
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3157
|
+
className: FallbacksCard_module_css_default.sectionHeading,
|
|
3158
|
+
id: "fallbacks-subagents",
|
|
3159
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3160
|
+
className: FallbacksCard_module_css_default.sectionHeadingText,
|
|
3161
|
+
children: t("subagents.label")
|
|
3162
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3163
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
3164
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3165
|
+
type: "button",
|
|
3166
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
3167
|
+
disabled: !subDirty || saving,
|
|
3168
|
+
onClick: () => {
|
|
3169
|
+
discardSection("sub");
|
|
3170
|
+
},
|
|
3171
|
+
children: t("discard")
|
|
3172
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3173
|
+
type: "button",
|
|
3174
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
3175
|
+
disabled: !writable || saving || !subDirty,
|
|
3176
|
+
onClick: () => {
|
|
3177
|
+
save("sub");
|
|
3178
|
+
},
|
|
3179
|
+
children: saving ? t("save.saving") : t("save")
|
|
3180
|
+
})]
|
|
3181
|
+
})]
|
|
3182
|
+
}),
|
|
3183
|
+
validationErrors.sub.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3184
|
+
className: FallbacksCard_module_css_default.error,
|
|
3185
|
+
role: "alert",
|
|
3186
|
+
children: `${t("validation.blocked")}${validationErrors.sub.join("; ")}`
|
|
3187
|
+
}),
|
|
3188
|
+
lastSaveSection === "sub" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3189
|
+
className: FallbacksCard_module_css_default.error,
|
|
3190
|
+
role: "alert",
|
|
3191
|
+
children: t("error.generic", { message: state.error })
|
|
3192
|
+
}),
|
|
3193
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3194
|
+
className: FallbacksCard_module_css_default.field,
|
|
3195
|
+
role: "group",
|
|
3196
|
+
"aria-labelledby": "fallbacks-roles-list",
|
|
3197
|
+
children: [
|
|
3198
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3199
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3200
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3201
|
+
id: "fallbacks-roles-list",
|
|
3202
|
+
children: t("roles.list.label")
|
|
3203
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3204
|
+
label: t("roles.list.tooltip"),
|
|
3205
|
+
disabled: !writable
|
|
3206
|
+
})]
|
|
3207
|
+
}),
|
|
3208
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3209
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3210
|
+
children: t("roles.list.hint")
|
|
3211
|
+
}),
|
|
3212
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3213
|
+
className: FallbacksCard_module_css_default.list,
|
|
3214
|
+
children: roleRows.map((row, index) => {
|
|
3215
|
+
const invalid = invalidRoleIds?.has(row.id.trim()) ?? false;
|
|
3216
|
+
const seed = seededIds.get(row.id.trim());
|
|
3217
|
+
const roleSummary = row.selectors.map(selectorRowToRaw).find((entry) => entry !== "") ?? row.fallback;
|
|
3218
|
+
const roleExpanded = !row.collapsed || !writable;
|
|
3219
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3220
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3221
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3222
|
+
className: FallbacksCard_module_css_default.collapseRow,
|
|
3223
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3224
|
+
type: "button",
|
|
3225
|
+
className: FallbacksCard_module_css_default.collapseToggle,
|
|
3226
|
+
"aria-expanded": roleExpanded,
|
|
3227
|
+
"aria-label": t(roleExpanded ? "roles.collapse" : "roles.expand"),
|
|
3228
|
+
disabled: !writable,
|
|
3229
|
+
onClick: () => {
|
|
3230
|
+
updateRoleRow(index, { collapsed: !row.collapsed });
|
|
3231
|
+
},
|
|
2430
3232
|
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
|
-
}
|
|
3233
|
+
/* @__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 }),
|
|
3234
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3235
|
+
className: FallbacksCard_module_css_default.collapseTitle,
|
|
3236
|
+
children: row.id
|
|
2464
3237
|
}),
|
|
2465
3238
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2466
|
-
className: FallbacksCard_module_css_default.
|
|
2467
|
-
children:
|
|
3239
|
+
className: FallbacksCard_module_css_default.collapseMeta,
|
|
3240
|
+
children: roleSummary
|
|
2468
3241
|
})
|
|
2469
3242
|
]
|
|
3243
|
+
})
|
|
3244
|
+
}), roleExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3245
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3246
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3247
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3248
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3249
|
+
children: [
|
|
3250
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3251
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3252
|
+
children: t("roles.id")
|
|
3253
|
+
}),
|
|
3254
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3255
|
+
className: `${FallbacksCard_module_css_default.input} ${invalid ? FallbacksCard_module_css_default.inputInvalid : ""}`,
|
|
3256
|
+
value: row.id,
|
|
3257
|
+
placeholder: t("roles.idPlaceholder"),
|
|
3258
|
+
"aria-label": t("roles.id"),
|
|
3259
|
+
"aria-invalid": invalid ? true : void 0,
|
|
3260
|
+
disabled: !writable || seed !== void 0,
|
|
3261
|
+
onChange: (event) => {
|
|
3262
|
+
updateRoleRow(index, { id: event.target.value });
|
|
3263
|
+
}
|
|
3264
|
+
}),
|
|
3265
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3266
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3267
|
+
children: t("roles.id.hint")
|
|
3268
|
+
})
|
|
3269
|
+
]
|
|
3270
|
+
})
|
|
3271
|
+
}),
|
|
3272
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3273
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3274
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3275
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3276
|
+
children: [
|
|
3277
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3278
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3279
|
+
children: t("roles.persona")
|
|
3280
|
+
}),
|
|
3281
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
3282
|
+
rows: 3,
|
|
3283
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.inputTextarea}`,
|
|
3284
|
+
value: row.persona,
|
|
3285
|
+
placeholder: t("roles.personaPlaceholder"),
|
|
3286
|
+
"aria-label": t("roles.persona"),
|
|
3287
|
+
disabled: !writable,
|
|
3288
|
+
onChange: (event) => {
|
|
3289
|
+
updateRoleRow(index, { persona: event.target.value });
|
|
3290
|
+
}
|
|
3291
|
+
}),
|
|
3292
|
+
seed !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3293
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3294
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3295
|
+
className: FallbacksCard_module_css_default.pending,
|
|
3296
|
+
children: t(seed ? "roles.seedOverride" : "roles.seedDefault")
|
|
3297
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3298
|
+
variant: "outline",
|
|
3299
|
+
size: "sm",
|
|
3300
|
+
disabled: !writable || saving,
|
|
3301
|
+
onClick: () => {
|
|
3302
|
+
forceReseed.current = true;
|
|
3303
|
+
controller.revertSeed(row.id.trim()).then((persona) => {
|
|
3304
|
+
if (persona === void 0) return;
|
|
3305
|
+
updateRoleRow(index, { persona });
|
|
3306
|
+
});
|
|
3307
|
+
},
|
|
3308
|
+
children: t("roles.revertPersona")
|
|
3309
|
+
})]
|
|
3310
|
+
})
|
|
3311
|
+
]
|
|
3312
|
+
})
|
|
2470
3313
|
}),
|
|
2471
3314
|
/* @__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
|
-
|
|
3315
|
+
className: FallbacksCard_module_css_default.chainSelectors,
|
|
3316
|
+
children: [row.selectors.map((selector, selectorIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChainSelectorEditor, {
|
|
3317
|
+
selector,
|
|
3318
|
+
catalog: catalogOf(state),
|
|
3319
|
+
configuredProviders: state.configuredProviders,
|
|
3320
|
+
disabled: !writable,
|
|
3321
|
+
t,
|
|
3322
|
+
onChange: (patch) => {
|
|
3323
|
+
updateRoleSelector(index, selectorIndex, patch);
|
|
3324
|
+
},
|
|
3325
|
+
onRemove: () => {
|
|
3326
|
+
removeRoleSelector(index, selectorIndex);
|
|
3327
|
+
}
|
|
3328
|
+
}, selectorIndex)), row.selectors.every((selector) => selectorRowToRaw(selector) === "") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3329
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3330
|
+
children: seed !== void 0 ? t("roles.seedChainOptional", { id: row.id }) : t("validation.roleChainRequired", { id: row.id })
|
|
3331
|
+
})]
|
|
3332
|
+
}),
|
|
3333
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3334
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3335
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3336
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3337
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3338
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3339
|
+
children: t("roles.fallback")
|
|
3340
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3341
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3342
|
+
value: row.fallback,
|
|
3343
|
+
"aria-label": t("roles.fallback"),
|
|
2501
3344
|
disabled: !writable,
|
|
2502
3345
|
onChange: (event) => {
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
3346
|
+
updateRoleRow(index, { fallback: event.target.value });
|
|
3347
|
+
},
|
|
3348
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3349
|
+
value: "inherit-root",
|
|
3350
|
+
children: t("roles.fallback.inherit-root")
|
|
3351
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3352
|
+
value: "none",
|
|
3353
|
+
children: t("roles.fallback.none")
|
|
3354
|
+
})]
|
|
3355
|
+
})]
|
|
3356
|
+
})
|
|
3357
|
+
}),
|
|
3358
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3359
|
+
variant: "outline",
|
|
3360
|
+
size: "sm",
|
|
3361
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3362
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3363
|
+
onClick: () => {
|
|
3364
|
+
addRoleSelector(index);
|
|
3365
|
+
},
|
|
3366
|
+
children: t("roles.selector.add")
|
|
2513
3367
|
}),
|
|
3368
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3369
|
+
className: FallbacksCard_module_css_default.cardFoot,
|
|
3370
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3371
|
+
type: "button",
|
|
3372
|
+
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
3373
|
+
"data-tip": t("roles.remove"),
|
|
3374
|
+
"aria-label": t("roles.remove"),
|
|
3375
|
+
onClick: () => {
|
|
3376
|
+
removeRole(index);
|
|
3377
|
+
},
|
|
3378
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
3379
|
+
})
|
|
3380
|
+
})
|
|
3381
|
+
] })]
|
|
3382
|
+
}, index);
|
|
3383
|
+
})
|
|
3384
|
+
}),
|
|
3385
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3386
|
+
variant: "outline",
|
|
3387
|
+
size: "sm",
|
|
3388
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3389
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3390
|
+
onClick: addRole,
|
|
3391
|
+
children: t("roles.add")
|
|
3392
|
+
})
|
|
3393
|
+
]
|
|
3394
|
+
}),
|
|
3395
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3396
|
+
className: FallbacksCard_module_css_default.field,
|
|
3397
|
+
role: "group",
|
|
3398
|
+
"aria-labelledby": "fallbacks-roles-rules",
|
|
3399
|
+
children: [
|
|
3400
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3401
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3402
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3403
|
+
id: "fallbacks-roles-rules",
|
|
3404
|
+
children: t("roles.rules")
|
|
3405
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3406
|
+
label: t("roles.rules.tooltip"),
|
|
3407
|
+
disabled: !writable
|
|
3408
|
+
})]
|
|
3409
|
+
}),
|
|
3410
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3411
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3412
|
+
children: t("roles.rules.hint")
|
|
3413
|
+
}),
|
|
3414
|
+
state.catalogStatus === "error" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3415
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3416
|
+
children: t("catalog.error", { message: state.catalogError })
|
|
3417
|
+
}),
|
|
3418
|
+
state.catalogStatus === "ready" && state.catalogError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3419
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3420
|
+
children: t("catalog.partial", { message: state.catalogError })
|
|
3421
|
+
}),
|
|
3422
|
+
state.catalogStatus === "ready" && (state.groups.length === 0 || state.configuredProviders.length === 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3423
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3424
|
+
children: t("catalog.empty")
|
|
3425
|
+
}),
|
|
3426
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3427
|
+
className: FallbacksCard_module_css_default.list,
|
|
3428
|
+
children: ruleRows.map((row, index) => {
|
|
3429
|
+
const catalog = catalogOf(state);
|
|
3430
|
+
const providerRaw = selectionToRaw(row.provider);
|
|
3431
|
+
const group = catalog?.groups.find((entry) => entry.id === providerRaw);
|
|
3432
|
+
const providerOutside = row.provider?.kind === "outside";
|
|
3433
|
+
const providerUnconfigured = !providerOutside && providerRaw !== "" && (catalog?.providers.some((entry) => entry.provider === providerRaw) ?? false) && !state.configuredProviders.some((entry) => entry.provider === providerRaw);
|
|
3434
|
+
const modelOutside = row.model?.kind === "outside";
|
|
3435
|
+
const roleOutside = row.role !== "" && !roleOptions.includes(row.role);
|
|
3436
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3437
|
+
className: FallbacksCard_module_css_default.editorCard,
|
|
3438
|
+
children: [
|
|
2514
3439
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2515
|
-
className: FallbacksCard_module_css_default.
|
|
3440
|
+
className: FallbacksCard_module_css_default.ruleGrid,
|
|
2516
3441
|
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
|
-
|
|
3442
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3443
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3444
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3445
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3446
|
+
children: t("roles.rule.provider")
|
|
3447
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3448
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3449
|
+
value: providerRaw,
|
|
3450
|
+
onChange: (event) => {
|
|
3451
|
+
if (event.target.value === providerRaw) return;
|
|
3452
|
+
updateRuleRow(index, {
|
|
3453
|
+
provider: classifyProvider(event.target.value, catalog),
|
|
3454
|
+
model: null
|
|
3455
|
+
});
|
|
3456
|
+
},
|
|
3457
|
+
children: [
|
|
3458
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3459
|
+
value: "",
|
|
3460
|
+
children: t("roles.rule.provider.any")
|
|
3461
|
+
}),
|
|
3462
|
+
state.configuredProviders.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3463
|
+
value: entry.provider,
|
|
3464
|
+
children: entry.displayName
|
|
3465
|
+
}, entry.provider)),
|
|
3466
|
+
providerUnconfigured && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3467
|
+
value: providerRaw,
|
|
3468
|
+
children: `${providerRaw}${t("catalog.unconfigured.short")}`
|
|
3469
|
+
}),
|
|
3470
|
+
providerOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3471
|
+
value: providerRaw,
|
|
3472
|
+
children: `${providerRaw}${t("catalog.outside.short")}`
|
|
3473
|
+
})
|
|
3474
|
+
]
|
|
3475
|
+
})]
|
|
2537
3476
|
}),
|
|
2538
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
}
|
|
2549
|
-
|
|
3477
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3478
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3479
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3480
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3481
|
+
children: t("roles.rule.model")
|
|
3482
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3483
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3484
|
+
value: selectionToRaw(row.model),
|
|
3485
|
+
onChange: (event) => {
|
|
3486
|
+
updateRuleRow(index, { model: classifyModel(providerRaw, event.target.value, catalog) });
|
|
3487
|
+
},
|
|
3488
|
+
children: [
|
|
3489
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3490
|
+
value: "",
|
|
3491
|
+
children: t("roles.rule.model.any")
|
|
3492
|
+
}),
|
|
3493
|
+
(group?.models ?? []).map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3494
|
+
value: model.id,
|
|
3495
|
+
children: model.name
|
|
3496
|
+
}, model.id)),
|
|
3497
|
+
modelOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3498
|
+
value: selectionToRaw(row.model),
|
|
3499
|
+
children: `${selectionToRaw(row.model)}${t("catalog.outside.short")}`
|
|
3500
|
+
})
|
|
3501
|
+
]
|
|
3502
|
+
})]
|
|
2550
3503
|
}),
|
|
2551
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2552
|
-
className: FallbacksCard_module_css_default.
|
|
2553
|
-
children:
|
|
3504
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3505
|
+
className: FallbacksCard_module_css_default.ruleCell,
|
|
3506
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3507
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3508
|
+
children: t("roles.rule.role")
|
|
3509
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
3510
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.selectInput}`,
|
|
3511
|
+
value: row.role,
|
|
3512
|
+
disabled: !writable,
|
|
3513
|
+
onChange: (event) => {
|
|
3514
|
+
updateRuleRow(index, { role: event.target.value });
|
|
3515
|
+
},
|
|
3516
|
+
children: [
|
|
3517
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3518
|
+
value: "",
|
|
3519
|
+
children: t("roles.rule.roleSelectPlaceholder")
|
|
3520
|
+
}),
|
|
3521
|
+
roleOptions.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3522
|
+
value: id,
|
|
3523
|
+
children: id === "inherit" ? t("roles.rule.role.inherit") : id
|
|
3524
|
+
}, id)),
|
|
3525
|
+
roleOutside && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3526
|
+
value: row.role,
|
|
3527
|
+
children: `${row.role}${t("roles.rule.roleUndeclared.short")}`
|
|
3528
|
+
})
|
|
3529
|
+
]
|
|
3530
|
+
})]
|
|
2554
3531
|
})
|
|
2555
3532
|
]
|
|
3533
|
+
}),
|
|
3534
|
+
(providerOutside || modelOutside) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3535
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3536
|
+
children: [t("catalog.outside.hint"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3537
|
+
label: t("catalog.outside.tooltip"),
|
|
3538
|
+
disabled: !writable
|
|
3539
|
+
})]
|
|
3540
|
+
}),
|
|
3541
|
+
row.role === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3542
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3543
|
+
children: t("validation.ruleRoleRequired")
|
|
3544
|
+
}),
|
|
3545
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3546
|
+
className: FallbacksCard_module_css_default.cardFoot,
|
|
3547
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3548
|
+
type: "button",
|
|
3549
|
+
className: `${FallbacksCard_module_css_default.iconButton} ${FallbacksCard_module_css_default.iconButtonDanger}`,
|
|
3550
|
+
"data-tip": t("roles.removeRule"),
|
|
3551
|
+
"aria-label": t("roles.removeRule"),
|
|
3552
|
+
onClick: () => {
|
|
3553
|
+
setRuleRows((rows) => rows.filter((_, rowIndex) => rowIndex !== index));
|
|
3554
|
+
},
|
|
3555
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, {})
|
|
3556
|
+
})
|
|
2556
3557
|
})
|
|
2557
3558
|
]
|
|
2558
|
-
})
|
|
2559
|
-
|
|
2560
|
-
})
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
3559
|
+
}, index);
|
|
3560
|
+
})
|
|
3561
|
+
}),
|
|
3562
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3563
|
+
variant: "outline",
|
|
3564
|
+
size: "sm",
|
|
3565
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 14 }),
|
|
3566
|
+
className: FallbacksCard_module_css_default.addButton,
|
|
3567
|
+
onClick: () => {
|
|
3568
|
+
setRuleRows((rows) => [...rows, {
|
|
3569
|
+
provider: null,
|
|
3570
|
+
model: null,
|
|
3571
|
+
role: ""
|
|
3572
|
+
}]);
|
|
3573
|
+
},
|
|
3574
|
+
children: t("roles.addRule")
|
|
3575
|
+
})
|
|
3576
|
+
]
|
|
3577
|
+
}),
|
|
3578
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3579
|
+
className: FallbacksCard_module_css_default.field,
|
|
3580
|
+
role: "group",
|
|
3581
|
+
"aria-labelledby": "fallbacks-advanced",
|
|
3582
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3583
|
+
type: "button",
|
|
3584
|
+
className: FallbacksCard_module_css_default.sectionToggle,
|
|
3585
|
+
disabled: !writable,
|
|
3586
|
+
"aria-expanded": advancedVisible,
|
|
3587
|
+
"aria-controls": advancedVisible ? "fallbacks-advanced-body" : void 0,
|
|
3588
|
+
"aria-label": t(advancedVisible ? "advanced.collapse" : "advanced.expand"),
|
|
3589
|
+
onClick: () => {
|
|
3590
|
+
if (writable) setAdvancedOpen(!advancedOpen);
|
|
3591
|
+
},
|
|
3592
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3593
|
+
id: "fallbacks-advanced",
|
|
3594
|
+
className: FallbacksCard_module_css_default.sectionToggleText,
|
|
3595
|
+
children: t("advanced.label")
|
|
3596
|
+
}), /* @__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 })]
|
|
3597
|
+
}), advancedVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3598
|
+
id: "fallbacks-advanced-body",
|
|
3599
|
+
children: [
|
|
3600
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3601
|
+
className: FallbacksCard_module_css_default.checkboxRow,
|
|
3602
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3603
|
+
className: FallbacksCard_module_css_default.checkLabel,
|
|
3604
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3605
|
+
className: FallbacksCard_module_css_default.checkLabelTitle,
|
|
3606
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3607
|
+
htmlFor: "fallbacks-role-automatch",
|
|
3608
|
+
children: t("roleAutoMatch.label")
|
|
3609
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3610
|
+
label: t("roleAutoMatch.tooltip"),
|
|
3611
|
+
disabled: !writable
|
|
3612
|
+
})]
|
|
3613
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3614
|
+
className: FallbacksCard_module_css_default.checkLabelDesc,
|
|
3615
|
+
children: t("roleAutoMatch.hint")
|
|
3616
|
+
})]
|
|
3617
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3618
|
+
id: "fallbacks-role-automatch",
|
|
3619
|
+
type: "checkbox",
|
|
3620
|
+
className: FallbacksCard_module_css_default.checkbox,
|
|
3621
|
+
checked: scalars.roleAutoMatch,
|
|
3622
|
+
disabled: !writable,
|
|
3623
|
+
onChange: (event) => {
|
|
3624
|
+
updateScalars((draft) => {
|
|
3625
|
+
draft.roleAutoMatch = event.target.checked;
|
|
3626
|
+
});
|
|
3627
|
+
}
|
|
3628
|
+
})]
|
|
3629
|
+
}),
|
|
3630
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3631
|
+
className: FallbacksCard_module_css_default.field,
|
|
3632
|
+
role: "group",
|
|
3633
|
+
"aria-labelledby": "fallbacks-trigger-codes",
|
|
3634
|
+
children: [
|
|
3635
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3636
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3637
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3638
|
+
id: "fallbacks-trigger-codes",
|
|
3639
|
+
children: t("triggerCodes.label")
|
|
3640
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3641
|
+
label: t("triggerCodes.tooltip"),
|
|
3642
|
+
disabled: !writable
|
|
3643
|
+
})]
|
|
3644
|
+
}),
|
|
3645
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3646
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3647
|
+
children: t("triggerCodes.hint")
|
|
3648
|
+
}),
|
|
3649
|
+
KNOWN_TRIGGER_CODES.map((code) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3650
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3651
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3652
|
+
type: "checkbox",
|
|
3653
|
+
checked: scalars.triggerCodes.includes(code),
|
|
3654
|
+
onChange: (event) => {
|
|
3655
|
+
updateScalars((draft) => {
|
|
3656
|
+
draft.triggerCodes = withTriggerCode(draft.triggerCodes, code, event.target.checked);
|
|
3657
|
+
});
|
|
3658
|
+
}
|
|
3659
|
+
}), t(TRIGGER_CODE_LABELS[code])]
|
|
3660
|
+
}, code)),
|
|
3661
|
+
unknownCodes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3662
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3663
|
+
children: t("triggerCodes.extra", { codes: unknownCodes.join(", ") })
|
|
3664
|
+
})
|
|
3665
|
+
]
|
|
3666
|
+
}),
|
|
3667
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3668
|
+
className: FallbacksCard_module_css_default.field,
|
|
3669
|
+
role: "group",
|
|
3670
|
+
"aria-labelledby": "fallbacks-revert-policy",
|
|
3671
|
+
children: [
|
|
3672
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3673
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3674
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3675
|
+
id: "fallbacks-revert-policy",
|
|
3676
|
+
children: t("revertPolicy.label")
|
|
3677
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3678
|
+
label: t("revertPolicy.tooltip"),
|
|
3679
|
+
disabled: !writable
|
|
3680
|
+
})]
|
|
3681
|
+
}),
|
|
3682
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3683
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3684
|
+
children: t("revertPolicy.hint")
|
|
3685
|
+
}),
|
|
3686
|
+
["cooldown-expiry", "never"].map((policy) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3687
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3688
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3689
|
+
type: "radio",
|
|
3690
|
+
name: "fallbacks-revert-policy",
|
|
3691
|
+
checked: scalars.revertPolicy === policy,
|
|
3692
|
+
onChange: () => {
|
|
3693
|
+
updateScalars((draft) => {
|
|
3694
|
+
draft.revertPolicy = policy;
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3697
|
+
}), t(`revertPolicy.${policy}`)]
|
|
3698
|
+
}, policy))
|
|
3699
|
+
]
|
|
3700
|
+
}),
|
|
3701
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3702
|
+
className: FallbacksCard_module_css_default.numberFields,
|
|
3703
|
+
children: [
|
|
3704
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3705
|
+
className: FallbacksCard_module_css_default.field,
|
|
3706
|
+
children: [
|
|
3707
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3708
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3709
|
+
children: [
|
|
3710
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3711
|
+
htmlFor: "fallbacks-cooldown-ms",
|
|
3712
|
+
children: t("cooldownMs.label")
|
|
3713
|
+
}),
|
|
3714
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3715
|
+
label: t("cooldownMs.tooltip"),
|
|
3716
|
+
disabled: !writable
|
|
3717
|
+
}),
|
|
3718
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3719
|
+
className: FallbacksCard_module_css_default.defaultNote,
|
|
3720
|
+
children: [
|
|
3721
|
+
t("defaults.prefix"),
|
|
3722
|
+
": ",
|
|
3723
|
+
state.config.cooldownMs
|
|
3724
|
+
]
|
|
3725
|
+
})
|
|
3726
|
+
]
|
|
3727
|
+
}),
|
|
3728
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3729
|
+
id: "fallbacks-cooldown-ms",
|
|
3730
|
+
className: FallbacksCard_module_css_default.input,
|
|
3731
|
+
type: "number",
|
|
3732
|
+
min: 0,
|
|
3733
|
+
value: String(scalars.cooldownMs),
|
|
3734
|
+
disabled: !writable,
|
|
3735
|
+
onChange: (event) => {
|
|
3736
|
+
updateScalars((draft) => {
|
|
3737
|
+
draft.cooldownMs = parseCount(event.target.value);
|
|
3738
|
+
});
|
|
3739
|
+
}
|
|
3740
|
+
}),
|
|
3741
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3742
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3743
|
+
children: t("cooldownMs.hint")
|
|
3744
|
+
})
|
|
3745
|
+
]
|
|
3746
|
+
}),
|
|
3747
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3748
|
+
className: FallbacksCard_module_css_default.field,
|
|
3749
|
+
children: [
|
|
3750
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3751
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3752
|
+
children: [
|
|
3753
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3754
|
+
htmlFor: "fallbacks-max-switches",
|
|
3755
|
+
children: t("maxSwitchesPerStep.label")
|
|
3756
|
+
}),
|
|
3757
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3758
|
+
label: t("maxSwitchesPerStep.tooltip"),
|
|
3759
|
+
disabled: !writable
|
|
3760
|
+
}),
|
|
3761
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3762
|
+
className: FallbacksCard_module_css_default.defaultNote,
|
|
3763
|
+
children: [
|
|
3764
|
+
t("defaults.prefix"),
|
|
3765
|
+
": ",
|
|
3766
|
+
state.config.maxSwitchesPerStep
|
|
3767
|
+
]
|
|
3768
|
+
})
|
|
3769
|
+
]
|
|
3770
|
+
}),
|
|
3771
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3772
|
+
id: "fallbacks-max-switches",
|
|
3773
|
+
className: FallbacksCard_module_css_default.input,
|
|
3774
|
+
type: "number",
|
|
3775
|
+
min: 0,
|
|
3776
|
+
value: String(scalars.maxSwitchesPerStep),
|
|
3777
|
+
disabled: !writable,
|
|
3778
|
+
onChange: (event) => {
|
|
3779
|
+
updateScalars((draft) => {
|
|
3780
|
+
draft.maxSwitchesPerStep = parseCount(event.target.value);
|
|
3781
|
+
});
|
|
3782
|
+
}
|
|
3783
|
+
}),
|
|
3784
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3785
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3786
|
+
children: t("maxSwitchesPerStep.hint")
|
|
3787
|
+
})
|
|
3788
|
+
]
|
|
3789
|
+
}),
|
|
3790
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3791
|
+
className: FallbacksCard_module_css_default.field,
|
|
3792
|
+
children: [
|
|
3793
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3794
|
+
className: FallbacksCard_module_css_default.fieldLabel,
|
|
3795
|
+
children: [
|
|
3796
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
3797
|
+
htmlFor: "fallbacks-always-cap",
|
|
3798
|
+
children: t("alwaysModeRetryCap.label")
|
|
3799
|
+
}),
|
|
3800
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
|
|
3801
|
+
label: t("alwaysModeRetryCap.tooltip"),
|
|
3802
|
+
disabled: !writable
|
|
3803
|
+
}),
|
|
3804
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3805
|
+
className: FallbacksCard_module_css_default.defaultNote,
|
|
3806
|
+
children: [
|
|
3807
|
+
t("defaults.prefix"),
|
|
3808
|
+
": ",
|
|
3809
|
+
state.config.alwaysModeRetryCap
|
|
3810
|
+
]
|
|
3811
|
+
})
|
|
3812
|
+
]
|
|
3813
|
+
}),
|
|
3814
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3815
|
+
id: "fallbacks-always-cap",
|
|
3816
|
+
className: FallbacksCard_module_css_default.input,
|
|
3817
|
+
type: "number",
|
|
3818
|
+
min: 0,
|
|
3819
|
+
value: String(scalars.alwaysModeRetryCap),
|
|
3820
|
+
disabled: !writable,
|
|
3821
|
+
onChange: (event) => {
|
|
3822
|
+
updateScalars((draft) => {
|
|
3823
|
+
draft.alwaysModeRetryCap = parseCount(event.target.value);
|
|
3824
|
+
});
|
|
3825
|
+
}
|
|
3826
|
+
}),
|
|
3827
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3828
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3829
|
+
children: t("alwaysModeRetryCap.hint")
|
|
3830
|
+
})
|
|
3831
|
+
]
|
|
3832
|
+
})
|
|
3833
|
+
]
|
|
3834
|
+
}),
|
|
3835
|
+
validationErrors.advanced.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3836
|
+
className: FallbacksCard_module_css_default.error,
|
|
3837
|
+
role: "alert",
|
|
3838
|
+
children: `${t("validation.blocked")}${validationErrors.advanced.join("; ")}`
|
|
3839
|
+
}),
|
|
3840
|
+
lastSaveSection === "advanced" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3841
|
+
className: FallbacksCard_module_css_default.error,
|
|
3842
|
+
role: "alert",
|
|
3843
|
+
children: t("error.generic", { message: state.error })
|
|
3844
|
+
}),
|
|
3845
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3846
|
+
className: FallbacksCard_module_css_default.sectionActions,
|
|
3847
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3848
|
+
type: "button",
|
|
3849
|
+
className: `${FallbacksCard_module_css_default.secondaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
3850
|
+
disabled: !advancedDirty || saving,
|
|
3851
|
+
onClick: () => {
|
|
3852
|
+
discardSection("advanced");
|
|
3853
|
+
},
|
|
3854
|
+
children: t("discard")
|
|
3855
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3856
|
+
type: "button",
|
|
3857
|
+
className: `${FallbacksCard_module_css_default.primaryButton} ${FallbacksCard_module_css_default.sectionAction}`,
|
|
3858
|
+
disabled: !writable || saving || !advancedDirty,
|
|
3859
|
+
onClick: () => {
|
|
3860
|
+
save("advanced");
|
|
3861
|
+
},
|
|
3862
|
+
children: saving ? t("save.saving") : t("save")
|
|
3863
|
+
})]
|
|
3864
|
+
})
|
|
3865
|
+
]
|
|
3866
|
+
})]
|
|
3867
|
+
})
|
|
3868
|
+
]
|
|
3869
|
+
})
|
|
3870
|
+
]
|
|
3871
|
+
}),
|
|
3872
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3873
|
+
className: FallbacksCard_module_css_default.statusBlock,
|
|
3874
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3875
|
+
className: FallbacksCard_module_css_default.statusTitle,
|
|
3876
|
+
children: t("status.title")
|
|
3877
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
3878
|
+
className: FallbacksCard_module_css_default.statusLine,
|
|
3879
|
+
role: state.switchesStatus === "error" ? "alert" : void 0,
|
|
2568
3880
|
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
|
-
]
|
|
3881
|
+
className: FallbacksCard_module_css_default.statusLineLabel,
|
|
3882
|
+
children: t("status.switches.label")
|
|
3883
|
+
}), switchesLine]
|
|
3884
|
+
})]
|
|
3885
|
+
})
|
|
3886
|
+
]
|
|
3887
|
+
})]
|
|
2636
3888
|
});
|
|
2637
3889
|
}
|
|
2638
3890
|
//#endregion
|