dsh-llm-fallbacks 0.4.2 → 0.4.4
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 +44 -16
- package/README.zh-CN.md +44 -16
- package/dist/chains.d.ts +24 -5
- package/dist/client/SubagentRoleBadge.d.ts +23 -0
- package/dist/client/fallbacks-store.d.ts +58 -17
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +368 -195
- package/dist/client/locales.d.ts +14 -6
- package/dist/config.d.ts +1 -1
- package/dist/events.d.ts +5 -3
- package/dist/gateway.d.ts +55 -2
- package/dist/index.d.ts +34 -5
- package/dist/index.js +204 -67
- package/dist/presets.d.ts +7 -4
- package/dist/seeds.d.ts +61 -7
- package/dist/state.d.ts +20 -0
- package/dist/time-slots.d.ts +19 -10
- package/dist/tui-settings.d.ts +8 -6
- package/dist/tui.d.ts +12 -5
- package/package.json +44 -24
- package/scripts/build-client.ts +15 -6
- package/scripts/prepare-release.ts +1 -1
- package/scripts/repair-fallbacks-switch-logs.ts +97 -129
package/dist/client/index.js
CHANGED
|
@@ -198,6 +198,12 @@ window.__ModuleLoader__.load({
|
|
|
198
198
|
raw: trimmed
|
|
199
199
|
};
|
|
200
200
|
}
|
|
201
|
+
/** The two official all-day tail ids (XOR — exactly one legal tail). */
|
|
202
|
+
const OFFICIAL_ALL_DAY_IDS = ["deepseek-official/deepseek-flash", "deepseek-official/deepseek-pro"];
|
|
203
|
+
/** Whether `id` is one of the two official all-day tail ids. */
|
|
204
|
+
function isOfficialAllDayId(id) {
|
|
205
|
+
return id === "deepseek-official/deepseek-flash" || id === "deepseek-official/deepseek-pro";
|
|
206
|
+
}
|
|
201
207
|
/**
|
|
202
208
|
* Frozen preset windows (UTC+8). `liang-peak` and `glm-peak` are
|
|
203
209
|
* Monday–Friday only (day mask `[1, 2, 3, 4, 5]`); their valleys are the
|
|
@@ -402,17 +408,18 @@ window.__ModuleLoader__.load({
|
|
|
402
408
|
}
|
|
403
409
|
/**
|
|
404
410
|
* All-day conformance (P6): the all-day chain is conforming when its LAST
|
|
405
|
-
* entry (the tail — the card's 默认模型 panel) is exactly one official
|
|
406
|
-
* model — Flash
|
|
407
|
-
* the ordered walk before that last-resort fallback. An empty chain or
|
|
408
|
-
* chain whose tail is not an official
|
|
409
|
-
*
|
|
410
|
-
* the raw chain stays
|
|
411
|
+
* entry (the tail — the card's 默认模型 panel) is exactly one official
|
|
412
|
+
* model — Flash or Pro (XOR). Leading entries (the card's 默认降级链 block)
|
|
413
|
+
* are the ordered walk before that last-resort fallback. An empty chain or
|
|
414
|
+
* a chain whose tail is not an official model (including the retired V4
|
|
415
|
+
* ids) keeps slot rows inert and refuses the virtual-row
|
|
416
|
+
* override/delegate; the v0.2.2 failure walk over the raw chain stays
|
|
417
|
+
* verbatim.
|
|
411
418
|
*/
|
|
412
419
|
function isAllDayConforming(chain) {
|
|
413
420
|
if (chain.length < 1) return false;
|
|
414
421
|
const tail = chain[chain.length - 1];
|
|
415
|
-
return tail
|
|
422
|
+
return isOfficialAllDayId(tail);
|
|
416
423
|
}
|
|
417
424
|
/**
|
|
418
425
|
* Slot winner + display label (P5): drives 分时切换 detection (per-root-agent
|
|
@@ -527,16 +534,30 @@ window.__ModuleLoader__.load({
|
|
|
527
534
|
/**
|
|
528
535
|
* Shape-guard the wire `seeds` badge field (spec §9.4): only `{ id,
|
|
529
536
|
* overridden }` entries survive — the `legacyKeys` element-filter
|
|
530
|
-
* precedent.
|
|
531
|
-
*
|
|
532
|
-
*
|
|
537
|
+
* precedent. `source` is optional on the wire (gateway version skew): a
|
|
538
|
+
* present-and-string label is kept, an absent/malformed one drops the
|
|
539
|
+
* field while the entry itself still parses — consumers treat a missing
|
|
540
|
+
* label as "no badge" (the degradation path, never an error). A blank or
|
|
541
|
+
* whitespace-only label counts as malformed (it would render a textless
|
|
542
|
+
* badge). Entries are
|
|
543
|
+
* NORMALIZED to the known keys, so a wire entry can never smuggle a
|
|
544
|
+
* non-string `source` past the guard's type. A non-array value resolves
|
|
545
|
+
* to `[]`; malformed entries are dropped, so an all-bad array also lands
|
|
546
|
+
* `[]`. The store never trusts a misshapen badge field.
|
|
533
547
|
*/
|
|
534
548
|
function parseSeedsWire(value) {
|
|
535
549
|
if (!Array.isArray(value)) return [];
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
550
|
+
const entries = [];
|
|
551
|
+
for (const entry of value) {
|
|
552
|
+
if (!isRecord(entry)) continue;
|
|
553
|
+
if (typeof entry.id !== "string" || typeof entry.overridden !== "boolean") continue;
|
|
554
|
+
entries.push({
|
|
555
|
+
id: entry.id,
|
|
556
|
+
overridden: entry.overridden,
|
|
557
|
+
...typeof entry.source === "string" && entry.source.trim() !== "" ? { source: entry.source } : {}
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
return entries;
|
|
540
561
|
}
|
|
541
562
|
function parsePolicyRoute(value) {
|
|
542
563
|
if (!isRecord(value)) return void 0;
|
|
@@ -588,14 +609,47 @@ window.__ModuleLoader__.load({
|
|
|
588
609
|
if (!isRecord(value) || !("subagentPolicy" in value)) return fallback;
|
|
589
610
|
return parseSubagentPolicyWire(value.subagentPolicy);
|
|
590
611
|
}
|
|
591
|
-
/**
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
612
|
+
/**
|
|
613
|
+
* Shape-guard one wire role record (`fallbacks/subagent-roles` readback).
|
|
614
|
+
* A non-object, a blank/non-string `role`, or a non-number `at` fails the
|
|
615
|
+
* WHOLE record (`undefined` → the badge renders nothing). A present-but-
|
|
616
|
+
* malformed `model` drops the FIELD while the record still parses (the
|
|
617
|
+
* `parseSeedsWire` `source` rule) — the badge then hovers the role alone
|
|
618
|
+
* instead of disappearing. Records are NORMALIZED to the known keys, so a
|
|
619
|
+
* wire record can never smuggle a non-string `model` past the guard's type.
|
|
620
|
+
*/
|
|
621
|
+
function parseSubagentRoleRecord(value) {
|
|
622
|
+
if (!isRecord(value)) return void 0;
|
|
623
|
+
if (typeof value.role !== "string" || value.role.trim() === "") return void 0;
|
|
624
|
+
if (typeof value.at !== "number") return void 0;
|
|
625
|
+
const model = parsePolicyRoute(value.model);
|
|
626
|
+
return {
|
|
627
|
+
role: value.role,
|
|
628
|
+
...model === void 0 ? {} : { model },
|
|
629
|
+
at: value.at
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Read this session's dispatch-resolved role record through the plugin
|
|
634
|
+
* gateway channel (plan subagent-role-badge T3): the batch-of-ids endpoint
|
|
635
|
+
* called with the one id the badge cares about. NEVER throws — a channel
|
|
636
|
+
* down, an old gateway without the endpoint (rpc failure), or a malformed
|
|
637
|
+
* payload all resolve `undefined` (the badge renders nothing —
|
|
638
|
+
* degrade-never-crash, the fail-closed shape of `parseSubagentPolicyWire`).
|
|
639
|
+
* @param rpc - the connection's generic RPC caller (`/api` channel).
|
|
640
|
+
* @param sessionId - the session whose record to read.
|
|
641
|
+
* @returns the parsed record, or `undefined` when absent/failed.
|
|
642
|
+
*/
|
|
643
|
+
async function fetchSubagentRoleRecord(rpc, sessionId) {
|
|
644
|
+
try {
|
|
645
|
+
const result = await rpc.call("/api", "fallbacks/subagent-roles", { args: { ids: [sessionId] } });
|
|
646
|
+
if (!result.ok) return void 0;
|
|
647
|
+
const value = result.value;
|
|
648
|
+
if (!isRecord(value)) return void 0;
|
|
649
|
+
return parseSubagentRoleRecord(value[sessionId]);
|
|
650
|
+
} catch {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
599
653
|
}
|
|
600
654
|
/**
|
|
601
655
|
* The provider dropdown's offer set (spec §2.5 D-4): catalog providers whose
|
|
@@ -862,7 +916,8 @@ window.__ModuleLoader__.load({
|
|
|
862
916
|
persona: role.persona,
|
|
863
917
|
selectors: (role.chain ?? []).map((entry) => entryToSelectorRow(entry, catalog)),
|
|
864
918
|
fallback: role.fallback ?? "inherit-root",
|
|
865
|
-
collapsed: true
|
|
919
|
+
collapsed: true,
|
|
920
|
+
personaOpen: false
|
|
866
921
|
}));
|
|
867
922
|
}
|
|
868
923
|
/** Rebuild the declared roles from edited rows; empty selectors drop out. */
|
|
@@ -1220,55 +1275,18 @@ window.__ModuleLoader__.load({
|
|
|
1220
1275
|
}
|
|
1221
1276
|
}
|
|
1222
1277
|
/**
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1225
|
-
*
|
|
1226
|
-
*
|
|
1227
|
-
*
|
|
1228
|
-
*
|
|
1229
|
-
*
|
|
1230
|
-
*
|
|
1231
|
-
*
|
|
1232
|
-
*
|
|
1233
|
-
* Returns the seed-default persona when the outcome is `{ reverted:
|
|
1234
|
-
* true, persona }` — including the persist no-op (persisted already
|
|
1235
|
-
* equals the seed). The card applies that string to the row's **draft**
|
|
1236
|
-
* so an unsaved persona edit still snaps back (issue #59).
|
|
1237
|
-
* @param id - the seeded role id; the host matches it by trimmed id
|
|
1238
|
-
* against the seed registry (spec §9.3).
|
|
1278
|
+
* Read one session's dispatch-resolved subagent role record through the
|
|
1279
|
+
* gateway channel (plan subagent-role-badge T3 — the session-header badge's
|
|
1280
|
+
* data face). Thin delegate over {@link fetchSubagentRoleRecord} on the
|
|
1281
|
+
* SAME rpc caller the store rides: the batch-of-ids readback called with
|
|
1282
|
+
* the one id the badge cares about. Never throws — a channel down, an old
|
|
1283
|
+
* gateway without the endpoint, or a malformed payload all resolve
|
|
1284
|
+
* `undefined` (the badge renders nothing).
|
|
1285
|
+
* @param sessionId - the session whose record to read.
|
|
1286
|
+
* @returns the parsed record, or `undefined` when absent/failed.
|
|
1239
1287
|
*/
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
if (!state.writable || state.status === "saving") return void 0;
|
|
1243
|
-
const generation = ++this.writeGeneration;
|
|
1244
|
-
this.store.update((draft) => {
|
|
1245
|
-
draft.status = "saving";
|
|
1246
|
-
draft.error = null;
|
|
1247
|
-
});
|
|
1248
|
-
try {
|
|
1249
|
-
const result = await this.rpc.call("/api", "fallbacks/revert-seed", { args: { id } });
|
|
1250
|
-
if (generation !== this.writeGeneration) return void 0;
|
|
1251
|
-
if (!result.ok) throw result.error;
|
|
1252
|
-
const value = result.value;
|
|
1253
|
-
const config = value !== null && typeof value === "object" && "config" in value ? value.config : void 0;
|
|
1254
|
-
let legacyKeys = this.store.getSnapshot().legacyKeys;
|
|
1255
|
-
if (value !== null && typeof value === "object" && "legacyKeys" in value) {
|
|
1256
|
-
const wireLegacyKeys = value.legacyKeys;
|
|
1257
|
-
if (Array.isArray(wireLegacyKeys)) legacyKeys = wireLegacyKeys.filter((key) => typeof key === "string");
|
|
1258
|
-
}
|
|
1259
|
-
let seeds = this.store.getSnapshot().seeds;
|
|
1260
|
-
if (value !== null && typeof value === "object" && "seeds" in value) {
|
|
1261
|
-
const wireSeeds = value.seeds;
|
|
1262
|
-
if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
|
|
1263
|
-
}
|
|
1264
|
-
const subagentPolicy = subagentPolicyFromWire(value, this.store.getSnapshot().subagentPolicy);
|
|
1265
|
-
this.accept(config, true, legacyKeys, seeds, subagentPolicy);
|
|
1266
|
-
return revertOutcomePersona(value);
|
|
1267
|
-
} catch (error) {
|
|
1268
|
-
if (generation !== this.writeGeneration) return void 0;
|
|
1269
|
-
this.fail(error);
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1288
|
+
fetchSubagentRole(sessionId) {
|
|
1289
|
+
return fetchSubagentRoleRecord(this.rpc, sessionId);
|
|
1272
1290
|
}
|
|
1273
1291
|
/** Stop in-flight responses from publishing after plugin disposal. */
|
|
1274
1292
|
dispose() {
|
|
@@ -1457,10 +1475,11 @@ window.__ModuleLoader__.load({
|
|
|
1457
1475
|
"timeSlots.day.fri": "五",
|
|
1458
1476
|
"timeSlots.day.sat": "六",
|
|
1459
1477
|
"timeSlots.selector.add": "添加选择器",
|
|
1460
|
-
"allDay.hint": "全天链的最后一档兜底:官方
|
|
1461
|
-
"allDay.flash": "官方
|
|
1462
|
-
"allDay.pro": "官方
|
|
1463
|
-
"allDay.
|
|
1478
|
+
"allDay.hint": "全天链的最后一档兜底:官方 Flash 或 Pro 二选一",
|
|
1479
|
+
"allDay.flash": "官方 Flash(deepseek-official/deepseek-flash)",
|
|
1480
|
+
"allDay.pro": "官方 Pro(deepseek-official/deepseek-pro)",
|
|
1481
|
+
"allDay.proCaveat": "(暂不可用)",
|
|
1482
|
+
"allDay.nonconforming": "当前默认模型不合法:请选择官方 Flash 或 Pro 后保存",
|
|
1464
1483
|
"roles.list.label": "角色实体",
|
|
1465
1484
|
"roles.list.hint": "先声明角色,规则才能引用",
|
|
1466
1485
|
"roles.list.tooltip": "角色 id 须匹配 /^[a-z0-9-]{1,32}$/ 且唯一;\"inherit\" 为保留字,不能用作角色 id。",
|
|
@@ -1469,9 +1488,11 @@ window.__ModuleLoader__.load({
|
|
|
1469
1488
|
"roles.idPlaceholder": "例如 reviewer",
|
|
1470
1489
|
"roles.persona": "人格提示",
|
|
1471
1490
|
"roles.personaPlaceholder": "例如:你是资深代码审查员",
|
|
1472
|
-
"roles.
|
|
1473
|
-
"roles.
|
|
1474
|
-
"roles.
|
|
1491
|
+
"roles.persona.expand": "展开人格提示",
|
|
1492
|
+
"roles.persona.collapse": "收起人格提示",
|
|
1493
|
+
"roles.persona.empty": "(未设置)",
|
|
1494
|
+
"roles.seedSource.bundled": "内置",
|
|
1495
|
+
"roles.seedSource.user": "用户",
|
|
1475
1496
|
"roles.seedChainOptional": "角色 \"{id}\" 为 seed 角色:链可留空,保存不会被拦截",
|
|
1476
1497
|
"roles.fallback": "链拼接策略",
|
|
1477
1498
|
"roles.fallback.inherit-root": "继承 root(角色链后追加 rootChain)",
|
|
@@ -1501,7 +1522,7 @@ window.__ModuleLoader__.load({
|
|
|
1501
1522
|
"validation.ruleRoleUndeclared": "规则引用了未声明的角色 \"{role}\"",
|
|
1502
1523
|
"validation.ruleRoleRequired": "规则未选择角色:请选择目标角色,或删除该行",
|
|
1503
1524
|
"validation.roleChainRequired": "角色 \"{id}\" 未配置模型:请至少添加一条链选择器(模型配置)",
|
|
1504
|
-
"validation.allDayRequired": "默认模型必须二选一:官方
|
|
1525
|
+
"validation.allDayRequired": "默认模型必须二选一:官方 Flash 或 Pro",
|
|
1505
1526
|
"validation.slotChainRequired": "分时槽未配置模型:请至少添加一条链选择器",
|
|
1506
1527
|
"validation.slotWindow": "分时槽开始/结束时间须为 HH:mm 格式",
|
|
1507
1528
|
"validation.slotDays": "星期取值须为 0–6 的整数",
|
|
@@ -1540,6 +1561,7 @@ window.__ModuleLoader__.load({
|
|
|
1540
1561
|
"chat.switch.summary": "{from} → {to}({reason})",
|
|
1541
1562
|
"chat.switch.summary.roleInject": "({reason})",
|
|
1542
1563
|
"chat.switch.roleMap": "{role} → {model}",
|
|
1564
|
+
"subagentRole.hover": "{role} → {model}",
|
|
1543
1565
|
"defaults.prefix": "默认值",
|
|
1544
1566
|
"save": "保存",
|
|
1545
1567
|
"save.saving": "保存中…",
|
|
@@ -1649,10 +1671,11 @@ window.__ModuleLoader__.load({
|
|
|
1649
1671
|
"timeSlots.day.fri": "Fri",
|
|
1650
1672
|
"timeSlots.day.sat": "Sat",
|
|
1651
1673
|
"timeSlots.selector.add": "Add selector",
|
|
1652
|
-
"allDay.hint": "Last-resort fallback of the all-day chain: official
|
|
1653
|
-
"allDay.flash": "Official
|
|
1654
|
-
"allDay.pro": "Official
|
|
1655
|
-
"allDay.
|
|
1674
|
+
"allDay.hint": "Last-resort fallback of the all-day chain: official Flash or Pro (pick exactly one)",
|
|
1675
|
+
"allDay.flash": "Official Flash (deepseek-official/deepseek-flash)",
|
|
1676
|
+
"allDay.pro": "Official Pro (deepseek-official/deepseek-pro)",
|
|
1677
|
+
"allDay.proCaveat": " (not yet available)",
|
|
1678
|
+
"allDay.nonconforming": "The current default model is not valid: pick official Flash or Pro before saving",
|
|
1656
1679
|
"roles.list.label": "Declared roles",
|
|
1657
1680
|
"roles.list.hint": "Declare roles before rules can reference them",
|
|
1658
1681
|
"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.",
|
|
@@ -1661,9 +1684,11 @@ window.__ModuleLoader__.load({
|
|
|
1661
1684
|
"roles.idPlaceholder": "e.g. reviewer",
|
|
1662
1685
|
"roles.persona": "Persona",
|
|
1663
1686
|
"roles.personaPlaceholder": "e.g. you are a senior code reviewer",
|
|
1664
|
-
"roles.
|
|
1665
|
-
"roles.
|
|
1666
|
-
"roles.
|
|
1687
|
+
"roles.persona.expand": "Expand persona",
|
|
1688
|
+
"roles.persona.collapse": "Collapse persona",
|
|
1689
|
+
"roles.persona.empty": "(not set)",
|
|
1690
|
+
"roles.seedSource.bundled": "bundled",
|
|
1691
|
+
"roles.seedSource.user": "User",
|
|
1667
1692
|
"roles.seedChainOptional": "Role \"{id}\" is a seed role: the chain may stay empty",
|
|
1668
1693
|
"roles.fallback": "Chain append",
|
|
1669
1694
|
"roles.fallback.inherit-root": "Inherit root (append rootChain after the role chain)",
|
|
@@ -1693,7 +1718,7 @@ window.__ModuleLoader__.load({
|
|
|
1693
1718
|
"validation.ruleRoleUndeclared": "Rule references undeclared role \"{role}\"",
|
|
1694
1719
|
"validation.ruleRoleRequired": "Rule has no role selected: pick a target role, or remove the row",
|
|
1695
1720
|
"validation.roleChainRequired": "Role \"{id}\" has no model config: add at least one chain entry",
|
|
1696
|
-
"validation.allDayRequired": "The default model must be exactly one official
|
|
1721
|
+
"validation.allDayRequired": "The default model must be exactly one official model (Flash or Pro)",
|
|
1697
1722
|
"validation.slotChainRequired": "Time-slot row has no models: add at least one chain entry",
|
|
1698
1723
|
"validation.slotWindow": "Time-slot start/end must use HH:mm format",
|
|
1699
1724
|
"validation.slotDays": "Days must be integers 0–6",
|
|
@@ -1732,6 +1757,7 @@ window.__ModuleLoader__.load({
|
|
|
1732
1757
|
"chat.switch.summary": "{from} → {to} ({reason})",
|
|
1733
1758
|
"chat.switch.summary.roleInject": "({reason})",
|
|
1734
1759
|
"chat.switch.roleMap": "{role} → {model}",
|
|
1760
|
+
"subagentRole.hover": "{role} → {model}",
|
|
1735
1761
|
"defaults.prefix": "Default",
|
|
1736
1762
|
"save": "Save",
|
|
1737
1763
|
"save.saving": "Saving…",
|
|
@@ -1779,13 +1805,13 @@ window.__ModuleLoader__.load({
|
|
|
1779
1805
|
}
|
|
1780
1806
|
//#endregion
|
|
1781
1807
|
//#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/FallbacksCard.module.css.mjs
|
|
1782
|
-
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\n._700006c9_policyStatus {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n._d4b67a81_policyStatusLabel {\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n._278bb4b3_policyStatusLine {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n}\n\n._da6387e5_policyStatusWarn {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._70effa64_iconButton::after {\n transition: none;\n }\n}\n";
|
|
1783
|
-
const tagId$
|
|
1784
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
1808
|
+
const css$3 = "\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._1285c19b_personaBriefRow {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 0;\n}\n\n._4b8f7345_personaBrief {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._2686400e_personaBriefEmpty {\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._4e4a07be_personaFull {\n margin: 0;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\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._52d6df87_seedBadge {\n flex: none;\n max-width: 40%;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\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-layer-1);\n color: var(--dsw-alias-label-secondary);\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\n._700006c9_policyStatus {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n._d4b67a81_policyStatusLabel {\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n._278bb4b3_policyStatusLine {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n}\n\n._da6387e5_policyStatusWarn {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._70effa64_iconButton::after {\n transition: none;\n }\n}\n";
|
|
1809
|
+
const tagId$3 = "dsh-llm-fallbacks/FallbacksCard.module.css";
|
|
1810
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
1785
1811
|
const tag = document.createElement("style");
|
|
1786
1812
|
tag.dataset.plugin = "dsh-llm-fallbacks";
|
|
1787
|
-
tag.dataset.pluginCss = tagId$
|
|
1788
|
-
tag.textContent = css$
|
|
1813
|
+
tag.dataset.pluginCss = tagId$3;
|
|
1814
|
+
tag.textContent = css$3;
|
|
1789
1815
|
document.head.appendChild(tag);
|
|
1790
1816
|
}
|
|
1791
1817
|
var FallbacksCard_module_css_default = {
|
|
@@ -1828,6 +1854,10 @@ window.__ModuleLoader__.load({
|
|
|
1828
1854
|
"dayCell": "_0330c1ed_dayCell",
|
|
1829
1855
|
"input": "_f9d86f7b_input",
|
|
1830
1856
|
"inputTextarea": "_3a9b42fd_inputTextarea",
|
|
1857
|
+
"personaBriefRow": "_1285c19b_personaBriefRow",
|
|
1858
|
+
"personaBrief": "_4b8f7345_personaBrief",
|
|
1859
|
+
"personaBriefEmpty": "_2686400e_personaBriefEmpty",
|
|
1860
|
+
"personaFull": "_4e4a07be_personaFull",
|
|
1831
1861
|
"inputInvalid": "_7b60337a_inputInvalid",
|
|
1832
1862
|
"selectInput": "_16eb7153_selectInput",
|
|
1833
1863
|
"numberFields": "_3e95886d_numberFields",
|
|
@@ -1840,6 +1870,7 @@ window.__ModuleLoader__.load({
|
|
|
1840
1870
|
"collapseToggle": "_a73efcc6_collapseToggle",
|
|
1841
1871
|
"collapseTitle": "_af017718_collapseTitle",
|
|
1842
1872
|
"collapseMeta": "_2cabe603_collapseMeta",
|
|
1873
|
+
"seedBadge": "_52d6df87_seedBadge",
|
|
1843
1874
|
"slotTag": "_7b04f727_slotTag",
|
|
1844
1875
|
"slotTagHighCost": "_c381e792_slotTagHighCost",
|
|
1845
1876
|
"slotTagMultiplier": "_23bdb6fc_slotTagMultiplier",
|
|
@@ -1951,8 +1982,10 @@ window.__ModuleLoader__.load({
|
|
|
1951
1982
|
* implemented without a store change); on a first mount the latch is false,
|
|
1952
1983
|
* so the healthy card starts (and stays) collapsed through its first load.
|
|
1953
1984
|
*/
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1985
|
+
const ALL_DAY_LABEL_KEYS = ["allDay.flash", "allDay.pro"];
|
|
1986
|
+
/** Optional caveat suffix per option (parallel to OFFICIAL_ALL_DAY_IDS):
|
|
1987
|
+
* Pro's radio is always disabled — its model is not yet in the catalog. */
|
|
1988
|
+
const ALL_DAY_CAVEAT_KEYS = [void 0, "allDay.proCaveat"];
|
|
1956
1989
|
const SLOT_PRESET_IDS = [
|
|
1957
1990
|
"liang-peak",
|
|
1958
1991
|
"liang-valley",
|
|
@@ -2005,19 +2038,19 @@ window.__ModuleLoader__.load({
|
|
|
2005
2038
|
/** Strict 24h `HH:mm` — the resolver's HHMM_RE twin (drift-guarded by the gateway reject-on-save). */
|
|
2006
2039
|
const HHMM_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
2007
2040
|
/**
|
|
2008
|
-
* The 默认模型 value for a chain: the official
|
|
2009
|
-
* is that model (Flash
|
|
2041
|
+
* The 默认模型 value for a chain: the official id when the chain TAIL
|
|
2042
|
+
* is that model (Flash or Pro XOR — leading 默认降级链 entries allowed);
|
|
2010
2043
|
* `''` for an empty chain or a chain whose last entry is not official
|
|
2011
2044
|
* (the panel reads back unselected and save validation blocks the value).
|
|
2012
2045
|
*/
|
|
2013
2046
|
function allDayModelOf(chain) {
|
|
2014
2047
|
const tail = chain.length >= 1 ? chain[chain.length - 1] : void 0;
|
|
2015
|
-
return tail
|
|
2048
|
+
return tail !== void 0 && isOfficialAllDayId(tail) ? tail : "";
|
|
2016
2049
|
}
|
|
2017
2050
|
/**
|
|
2018
|
-
* The 默认降级链 editor row: the leading entries BEFORE the official
|
|
2019
|
-
*
|
|
2020
|
-
* rides the accepted value until a 默认模型 pick).
|
|
2051
|
+
* The 默认降级链 editor row: the leading entries BEFORE the official tail
|
|
2052
|
+
* (Flash or Pro), or the whole chain while the tail is not official (the
|
|
2053
|
+
* draft rides the accepted value until a 默认模型 pick).
|
|
2021
2054
|
*/
|
|
2022
2055
|
function allDayChainRowOf(chain, catalog) {
|
|
2023
2056
|
return rootChainToRows(allDayModelOf(chain) === "" ? chain : chain.slice(0, -1), catalog)[0];
|
|
@@ -2052,8 +2085,8 @@ window.__ModuleLoader__.load({
|
|
|
2052
2085
|
* (AC-7 re-scope, PM decision 2026-08-17 Option A).
|
|
2053
2086
|
*
|
|
2054
2087
|
* All-day: rootChain is composed from the 默认降级链 editor's leading
|
|
2055
|
-
* selectors plus the 默认模型 tail (exactly one official
|
|
2056
|
-
* Pro). While no tail is selected the ACCEPTED chain rides through
|
|
2088
|
+
* selectors plus the 默认模型 tail (exactly one official model — Flash or
|
|
2089
|
+
* Pro XOR). While no tail is selected the ACCEPTED chain rides through
|
|
2057
2090
|
* untouched. `timeSlots` is rebuilt from the slot rows every render. `tz`
|
|
2058
2091
|
* is a card scalar: preset rows lock it to Asia/Shanghai; custom rows
|
|
2059
2092
|
* follow the selected timezone.
|
|
@@ -2089,6 +2122,22 @@ window.__ModuleLoader__.load({
|
|
|
2089
2122
|
};
|
|
2090
2123
|
}
|
|
2091
2124
|
/**
|
|
2125
|
+
* Badge label for one row's provenance (plan role-card-seeded-ux): every
|
|
2126
|
+
* row states where its seed state comes from. A live seed renders its
|
|
2127
|
+
* declaring set's label VERBATIM (case-preserved — no case-folding; the
|
|
2128
|
+
* unnamed case is the literal `external`), the bundled presets and the
|
|
2129
|
+
* operator's own rows resolve to their localized labels. `null` = no
|
|
2130
|
+
* badge: a currently-seeded row whose wire entry lacks `source` (gateway
|
|
2131
|
+
* version skew) — the degradation path, never an error.
|
|
2132
|
+
*/
|
|
2133
|
+
function seedBadgeLabel(seed, t) {
|
|
2134
|
+
if (seed === void 0) return t("roles.seedSource.user");
|
|
2135
|
+
if (seed.source === void 0) return null;
|
|
2136
|
+
if (seed.source === "bundled") return t("roles.seedSource.bundled");
|
|
2137
|
+
if (seed.source === "user") return t("roles.seedSource.user");
|
|
2138
|
+
return seed.source;
|
|
2139
|
+
}
|
|
2140
|
+
/**
|
|
2092
2141
|
* Pre-save validation of the assembled draft (spec §8 / plan Task 3):
|
|
2093
2142
|
* role id format/reserved word/duplicates, undeclared rule role references
|
|
2094
2143
|
* (only reachable through the synthetic outside option — the dropdown
|
|
@@ -2102,13 +2151,13 @@ window.__ModuleLoader__.load({
|
|
|
2102
2151
|
* {@link save} — the draft is never written. `persona` is free text and
|
|
2103
2152
|
* never validated.
|
|
2104
2153
|
*
|
|
2105
|
-
* `
|
|
2154
|
+
* `seedInfo` is the live trimmed-id → seed-entry map derived from
|
|
2106
2155
|
* `state.seeds` (spec §9.4): the empty-chain block relaxes for seeded ids
|
|
2107
2156
|
* only (spec §9.6 / AC-3 — a seeded role's chain is legitimately empty by
|
|
2108
|
-
* design, R4, and
|
|
2109
|
-
* behavior is byte-identical.
|
|
2157
|
+
* design, R4, and the row must stay persistable through a section save);
|
|
2158
|
+
* non-seeded behavior is byte-identical.
|
|
2110
2159
|
*/
|
|
2111
|
-
function validateDraft(draft, t,
|
|
2160
|
+
function validateDraft(draft, t, seedInfo) {
|
|
2112
2161
|
const errors = emptyValidationErrors();
|
|
2113
2162
|
const declaredIds = /* @__PURE__ */ new Set();
|
|
2114
2163
|
for (const role of draft.roles.list) {
|
|
@@ -2124,10 +2173,10 @@ window.__ModuleLoader__.load({
|
|
|
2124
2173
|
message: error.message
|
|
2125
2174
|
}));
|
|
2126
2175
|
}
|
|
2127
|
-
if ((role.chain ?? []).length === 0 && !
|
|
2176
|
+
if ((role.chain ?? []).length === 0 && !seedInfo.has(role.id.trim())) errors.sub.push(t("validation.roleChainRequired", { id: role.id }));
|
|
2128
2177
|
}
|
|
2129
2178
|
const allDayTail = draft.rootChain.length >= 1 ? draft.rootChain[draft.rootChain.length - 1] : void 0;
|
|
2130
|
-
if (allDayTail
|
|
2179
|
+
if (allDayTail === void 0 || !isOfficialAllDayId(allDayTail)) errors.main.push(t("validation.allDayRequired"));
|
|
2131
2180
|
for (const entry of draft.rootChain) try {
|
|
2132
2181
|
parseSelector(entry);
|
|
2133
2182
|
} catch (error) {
|
|
@@ -2422,7 +2471,6 @@ window.__ModuleLoader__.load({
|
|
|
2422
2471
|
]);
|
|
2423
2472
|
const dirty = mainDirty || subDirty || advancedDirty;
|
|
2424
2473
|
const firstSeedDone = (0, react.useRef)(false);
|
|
2425
|
-
const forceReseed = (0, react.useRef)(false);
|
|
2426
2474
|
(0, react.useEffect)(() => {
|
|
2427
2475
|
if (state.status !== "ready") return;
|
|
2428
2476
|
const key = JSON.stringify(state.config);
|
|
@@ -2430,10 +2478,8 @@ window.__ModuleLoader__.load({
|
|
|
2430
2478
|
seededConfigKey.current = key;
|
|
2431
2479
|
const firstSeed = !firstSeedDone.current;
|
|
2432
2480
|
firstSeedDone.current = true;
|
|
2433
|
-
const force = forceReseed.current;
|
|
2434
|
-
forceReseed.current = false;
|
|
2435
2481
|
const catalog = catalogOf(state);
|
|
2436
|
-
if (firstSeed ||
|
|
2482
|
+
if (firstSeed || !mainDirty) {
|
|
2437
2483
|
setAllDayModel(allDayModelOf(state.config.rootChain));
|
|
2438
2484
|
setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalog));
|
|
2439
2485
|
setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalog));
|
|
@@ -2443,11 +2489,11 @@ window.__ModuleLoader__.load({
|
|
|
2443
2489
|
tz: state.config.tz ?? "Asia/Shanghai"
|
|
2444
2490
|
}));
|
|
2445
2491
|
}
|
|
2446
|
-
if (firstSeed ||
|
|
2492
|
+
if (firstSeed || !subDirty) {
|
|
2447
2493
|
setRoleRows(rolesToRows(state.config.roles.list, catalog));
|
|
2448
2494
|
setRuleRows(rulesToRows(state.config.roles.rules, catalog));
|
|
2449
2495
|
}
|
|
2450
|
-
if (firstSeed ||
|
|
2496
|
+
if (firstSeed || !advancedDirty) setScalars((prev) => ({
|
|
2451
2497
|
...prev,
|
|
2452
2498
|
triggerCodes: [...state.config.triggerCodes],
|
|
2453
2499
|
cooldownMs: state.config.cooldownMs,
|
|
@@ -2635,7 +2681,8 @@ window.__ModuleLoader__.load({
|
|
|
2635
2681
|
persona: "",
|
|
2636
2682
|
selectors: [],
|
|
2637
2683
|
fallback: "inherit-root",
|
|
2638
|
-
collapsed: true
|
|
2684
|
+
collapsed: true,
|
|
2685
|
+
personaOpen: false
|
|
2639
2686
|
}]);
|
|
2640
2687
|
};
|
|
2641
2688
|
const removeRole = (index) => {
|
|
@@ -2666,8 +2713,11 @@ window.__ModuleLoader__.load({
|
|
|
2666
2713
|
const roleOptions = ruleRoleOptions({ list: roleRows });
|
|
2667
2714
|
const invalidRoleIds = validationAttempted ? collectInvalidRoleIds(roleRows) : null;
|
|
2668
2715
|
const invalidSlotRows = validationAttempted ? collectInvalidSlotRows(timeSlotRows) : null;
|
|
2669
|
-
const
|
|
2670
|
-
for (const seed of state.seeds)
|
|
2716
|
+
const seedInfo = /* @__PURE__ */ new Map();
|
|
2717
|
+
for (const seed of state.seeds) seedInfo.set(seed.id.trim(), {
|
|
2718
|
+
overridden: seed.overridden,
|
|
2719
|
+
source: seed.source
|
|
2720
|
+
});
|
|
2671
2721
|
const latestSwitch = state.switches[0];
|
|
2672
2722
|
let switchesLine;
|
|
2673
2723
|
if (state.switchesStatus === "error") switchesLine = t("status.switches.error", { message: state.switchesError });
|
|
@@ -2745,7 +2795,7 @@ window.__ModuleLoader__.load({
|
|
|
2745
2795
|
};
|
|
2746
2796
|
const save = (section) => {
|
|
2747
2797
|
setLastSaveSection(section);
|
|
2748
|
-
const errors = validateDraft(draft, t,
|
|
2798
|
+
const errors = validateDraft(draft, t, seedInfo);
|
|
2749
2799
|
if (section === "sub" && hasEmptyRuleRows) errors.sub.push(t("validation.ruleRoleRequired"));
|
|
2750
2800
|
if (errors[section].length > 0) {
|
|
2751
2801
|
setValidationErrors(errors);
|
|
@@ -2804,7 +2854,7 @@ window.__ModuleLoader__.load({
|
|
|
2804
2854
|
};
|
|
2805
2855
|
(0, react.useEffect)(() => {
|
|
2806
2856
|
if (!validationAttempted) return;
|
|
2807
|
-
const errors = validateDraft(draft, t,
|
|
2857
|
+
const errors = validateDraft(draft, t, seedInfo);
|
|
2808
2858
|
if (errors.main.length === 0 && errors.sub.length === 0 && errors.advanced.length === 0 && !ruleRows.some((row) => row.role === "")) {
|
|
2809
2859
|
setValidationErrors(emptyValidationErrors());
|
|
2810
2860
|
setValidationAttempted(false);
|
|
@@ -2817,7 +2867,6 @@ window.__ModuleLoader__.load({
|
|
|
2817
2867
|
]);
|
|
2818
2868
|
(0, react.useEffect)(() => {
|
|
2819
2869
|
if (state.status === "ready") setLastSaveSection(null);
|
|
2820
|
-
if (state.status === "error") forceReseed.current = false;
|
|
2821
2870
|
}, [state.status]);
|
|
2822
2871
|
const [userOpen, setUserOpen] = (0, react.useState)(false);
|
|
2823
2872
|
const [advancedOpen, setAdvancedOpen] = (0, react.useState)(false);
|
|
@@ -3410,36 +3459,28 @@ window.__ModuleLoader__.load({
|
|
|
3410
3459
|
className: FallbacksCard_module_css_default.list,
|
|
3411
3460
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3412
3461
|
className: FallbacksCard_module_css_default.editorCard,
|
|
3413
|
-
children: [
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
type: "radio",
|
|
3418
|
-
name: "fallbacks-all-day",
|
|
3419
|
-
checked: allDayModel === ALL_DAY_FLASH,
|
|
3420
|
-
disabled: !writable,
|
|
3421
|
-
onChange: () => {
|
|
3422
|
-
setAllDayModel(ALL_DAY_FLASH);
|
|
3423
|
-
}
|
|
3424
|
-
}), t("allDay.flash")]
|
|
3425
|
-
}),
|
|
3426
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3427
|
-
className: FallbacksCard_module_css_default.optionRow,
|
|
3428
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3462
|
+
children: [OFFICIAL_ALL_DAY_IDS.map((id, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3463
|
+
className: FallbacksCard_module_css_default.optionRow,
|
|
3464
|
+
children: [
|
|
3465
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3429
3466
|
type: "radio",
|
|
3430
3467
|
name: "fallbacks-all-day",
|
|
3431
|
-
checked: allDayModel ===
|
|
3432
|
-
disabled: !writable,
|
|
3468
|
+
checked: allDayModel === id,
|
|
3469
|
+
disabled: !writable || id === "deepseek-official/deepseek-pro",
|
|
3433
3470
|
onChange: () => {
|
|
3434
|
-
setAllDayModel(
|
|
3471
|
+
setAllDayModel(id);
|
|
3435
3472
|
}
|
|
3436
|
-
}),
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3473
|
+
}),
|
|
3474
|
+
t(ALL_DAY_LABEL_KEYS[index]),
|
|
3475
|
+
ALL_DAY_CAVEAT_KEYS[index] !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3476
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3477
|
+
children: t(ALL_DAY_CAVEAT_KEYS[index])
|
|
3478
|
+
})
|
|
3479
|
+
]
|
|
3480
|
+
}, id)), allDayModel === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3481
|
+
className: FallbacksCard_module_css_default.hint,
|
|
3482
|
+
children: t("allDay.nonconforming")
|
|
3483
|
+
})]
|
|
3443
3484
|
})
|
|
3444
3485
|
})
|
|
3445
3486
|
]
|
|
@@ -3536,7 +3577,9 @@ window.__ModuleLoader__.load({
|
|
|
3536
3577
|
className: FallbacksCard_module_css_default.list,
|
|
3537
3578
|
children: roleRows.map((row, index) => {
|
|
3538
3579
|
const invalid = invalidRoleIds?.has(row.id.trim()) ?? false;
|
|
3539
|
-
const seed =
|
|
3580
|
+
const seed = seedInfo.get(row.id.trim());
|
|
3581
|
+
const seedBadge = seedBadgeLabel(seed, t);
|
|
3582
|
+
const personaBlank = row.persona.trim() === "";
|
|
3540
3583
|
const roleSummary = row.selectors.map(selectorRowToRaw).find((entry) => entry !== "") ?? row.fallback;
|
|
3541
3584
|
const roleExpanded = !row.collapsed || !writable;
|
|
3542
3585
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -3558,6 +3601,11 @@ window.__ModuleLoader__.load({
|
|
|
3558
3601
|
className: FallbacksCard_module_css_default.collapseTitle,
|
|
3559
3602
|
children: row.id
|
|
3560
3603
|
}),
|
|
3604
|
+
seedBadge !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3605
|
+
className: FallbacksCard_module_css_default.seedBadge,
|
|
3606
|
+
title: seedBadge,
|
|
3607
|
+
children: seedBadge
|
|
3608
|
+
}),
|
|
3561
3609
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3562
3610
|
className: FallbacksCard_module_css_default.collapseMeta,
|
|
3563
3611
|
children: roleSummary
|
|
@@ -3565,7 +3613,7 @@ window.__ModuleLoader__.load({
|
|
|
3565
3613
|
]
|
|
3566
3614
|
})
|
|
3567
3615
|
}), roleExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3568
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3616
|
+
seed === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3569
3617
|
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3570
3618
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3571
3619
|
className: FallbacksCard_module_css_default.ruleCell,
|
|
@@ -3580,7 +3628,7 @@ window.__ModuleLoader__.load({
|
|
|
3580
3628
|
placeholder: t("roles.idPlaceholder"),
|
|
3581
3629
|
"aria-label": t("roles.id"),
|
|
3582
3630
|
"aria-invalid": invalid ? true : void 0,
|
|
3583
|
-
disabled: !writable
|
|
3631
|
+
disabled: !writable,
|
|
3584
3632
|
onChange: (event) => {
|
|
3585
3633
|
updateRoleRow(index, { id: event.target.value });
|
|
3586
3634
|
}
|
|
@@ -3596,42 +3644,46 @@ window.__ModuleLoader__.load({
|
|
|
3596
3644
|
className: FallbacksCard_module_css_default.ruleGrid,
|
|
3597
3645
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3598
3646
|
className: FallbacksCard_module_css_default.ruleCell,
|
|
3599
|
-
children: [
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
}
|
|
3633
|
-
|
|
3634
|
-
|
|
3647
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3648
|
+
className: FallbacksCard_module_css_default.ruleCellLabel,
|
|
3649
|
+
children: t("roles.persona")
|
|
3650
|
+
}), seed === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
3651
|
+
rows: 3,
|
|
3652
|
+
className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.inputTextarea}`,
|
|
3653
|
+
value: row.persona,
|
|
3654
|
+
placeholder: t("roles.personaPlaceholder"),
|
|
3655
|
+
"aria-label": t("roles.persona"),
|
|
3656
|
+
disabled: !writable,
|
|
3657
|
+
onChange: (event) => {
|
|
3658
|
+
updateRoleRow(index, { persona: event.target.value });
|
|
3659
|
+
}
|
|
3660
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3661
|
+
className: FallbacksCard_module_css_default.personaBriefRow,
|
|
3662
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3663
|
+
className: personaBlank ? `${FallbacksCard_module_css_default.personaBrief} ${FallbacksCard_module_css_default.personaBriefEmpty}` : FallbacksCard_module_css_default.personaBrief,
|
|
3664
|
+
children: personaBlank ? t("roles.persona.empty") : row.persona
|
|
3665
|
+
}), !personaBlank && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3666
|
+
role: "button",
|
|
3667
|
+
tabIndex: 0,
|
|
3668
|
+
className: FallbacksCard_module_css_default.iconButton,
|
|
3669
|
+
"aria-expanded": row.personaOpen,
|
|
3670
|
+
"aria-label": t(row.personaOpen ? "roles.persona.collapse" : "roles.persona.expand"),
|
|
3671
|
+
"data-tip": t(row.personaOpen ? "roles.persona.collapse" : "roles.persona.expand"),
|
|
3672
|
+
onClick: () => {
|
|
3673
|
+
updateRoleRow(index, { personaOpen: !row.personaOpen });
|
|
3674
|
+
},
|
|
3675
|
+
onKeyDown: (event) => {
|
|
3676
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
3677
|
+
event.preventDefault();
|
|
3678
|
+
updateRoleRow(index, { personaOpen: !row.personaOpen });
|
|
3679
|
+
}
|
|
3680
|
+
},
|
|
3681
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: row.personaOpen ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron })
|
|
3682
|
+
})]
|
|
3683
|
+
}), row.personaOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3684
|
+
className: FallbacksCard_module_css_default.personaFull,
|
|
3685
|
+
children: row.persona
|
|
3686
|
+
})] })]
|
|
3635
3687
|
})
|
|
3636
3688
|
}),
|
|
3637
3689
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -4212,13 +4264,13 @@ window.__ModuleLoader__.load({
|
|
|
4212
4264
|
}
|
|
4213
4265
|
//#endregion
|
|
4214
4266
|
//#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/GeneralFallbacksRow.module.css.mjs
|
|
4215
|
-
const css$
|
|
4216
|
-
const tagId$
|
|
4217
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
4267
|
+
const css$2 = "\n\n._440e1d7b_row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px 0;\n border-bottom: 1px solid var(--dsw-alias-border-l2);\n}\n\n._a4f2ceec_rowText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding-right: 48px;\n}\n\n._9865b509_title {\n font-size: 14px;\n font-weight: 400;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._10a44713_summary {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n._35648278_badge {\n flex: none;\n padding: 2px 10px;\n border-radius: 9px;\n font-size: 12px;\n line-height: 18px;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-tertiary);\n}\n\n._3b9e8609_badgeEnabled {\n color: var(--dsw-alias-state-success-primary);\n}\n";
|
|
4268
|
+
const tagId$2 = "dsh-llm-fallbacks/GeneralFallbacksRow.module.css";
|
|
4269
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
4218
4270
|
const tag = document.createElement("style");
|
|
4219
4271
|
tag.dataset.plugin = "dsh-llm-fallbacks";
|
|
4220
|
-
tag.dataset.pluginCss = tagId$
|
|
4221
|
-
tag.textContent = css$
|
|
4272
|
+
tag.dataset.pluginCss = tagId$2;
|
|
4273
|
+
tag.textContent = css$2;
|
|
4222
4274
|
document.head.appendChild(tag);
|
|
4223
4275
|
}
|
|
4224
4276
|
var GeneralFallbacksRow_module_css_default = {
|
|
@@ -4337,13 +4389,13 @@ window.__ModuleLoader__.load({
|
|
|
4337
4389
|
}
|
|
4338
4390
|
//#endregion
|
|
4339
4391
|
//#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/ConversationFallbackSwitch.module.css.mjs
|
|
4340
|
-
const css = "\n\n._ea99bbef_switchRow {\n display: flex;\n align-items: center;\n padding: 2px 0;\n font-size: 14px;\n line-height: 24px;\n}\n\n\n._02580bfd_switchTitle {\n flex: none;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n._88b2d18b_switchSep {\n flex: none;\n width: 2px;\n height: 2px;\n margin: 0 8px;\n border-radius: 1px;\n background: var(--dsw-alias-label-caption);\n}\n\n\n._7c8c1b6f_switchSummary {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._fdc977bc_roleBadge {\n flex: none;\n max-width: 96px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 12px;\n line-height: 20px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-primary);\n}\n\n\n._dce8ba28_roleModelMap {\n flex: 0 1 auto;\n min-width: 0;\n margin-left: 8px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--dsw-alias-label-secondary);\n}\n";
|
|
4341
|
-
const tagId = "dsh-llm-fallbacks/ConversationFallbackSwitch.module.css";
|
|
4342
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
4392
|
+
const css$1 = "\n\n._ea99bbef_switchRow {\n display: flex;\n align-items: center;\n padding: 2px 0;\n font-size: 14px;\n line-height: 24px;\n}\n\n\n._02580bfd_switchTitle {\n flex: none;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n._88b2d18b_switchSep {\n flex: none;\n width: 2px;\n height: 2px;\n margin: 0 8px;\n border-radius: 1px;\n background: var(--dsw-alias-label-caption);\n}\n\n\n._7c8c1b6f_switchSummary {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._fdc977bc_roleBadge {\n flex: none;\n max-width: 96px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 12px;\n line-height: 20px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-primary);\n}\n\n\n._dce8ba28_roleModelMap {\n flex: 0 1 auto;\n min-width: 0;\n margin-left: 8px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--dsw-alias-label-secondary);\n}\n";
|
|
4393
|
+
const tagId$1 = "dsh-llm-fallbacks/ConversationFallbackSwitch.module.css";
|
|
4394
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
4343
4395
|
const tag = document.createElement("style");
|
|
4344
4396
|
tag.dataset.plugin = "dsh-llm-fallbacks";
|
|
4345
|
-
tag.dataset.pluginCss = tagId;
|
|
4346
|
-
tag.textContent = css;
|
|
4397
|
+
tag.dataset.pluginCss = tagId$1;
|
|
4398
|
+
tag.textContent = css$1;
|
|
4347
4399
|
document.head.appendChild(tag);
|
|
4348
4400
|
}
|
|
4349
4401
|
var ConversationFallbackSwitch_module_css_default = {
|
|
@@ -4475,6 +4527,118 @@ window.__ModuleLoader__.load({
|
|
|
4475
4527
|
});
|
|
4476
4528
|
}
|
|
4477
4529
|
//#endregion
|
|
4530
|
+
//#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/SubagentRoleBadge.module.css.mjs
|
|
4531
|
+
const css = "\n\n._35648278_badge {\n display: inline-block;\n max-width: 120px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 12px;\n line-height: 20px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n vertical-align: middle;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-primary);\n}\n";
|
|
4532
|
+
const tagId = "dsh-llm-fallbacks/SubagentRoleBadge.module.css";
|
|
4533
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
4534
|
+
const tag = document.createElement("style");
|
|
4535
|
+
tag.dataset.plugin = "dsh-llm-fallbacks";
|
|
4536
|
+
tag.dataset.pluginCss = tagId;
|
|
4537
|
+
tag.textContent = css;
|
|
4538
|
+
document.head.appendChild(tag);
|
|
4539
|
+
}
|
|
4540
|
+
var SubagentRoleBadge_module_css_default = { "badge": "_35648278_badge" };
|
|
4541
|
+
//#endregion
|
|
4542
|
+
//#region src/client/SubagentRoleBadge.tsx
|
|
4543
|
+
/**
|
|
4544
|
+
* Session-header subagent role badge (plan subagent-role-badge T3): a
|
|
4545
|
+
* compact read-only pill in `conversation.session.header.utilities` showing
|
|
4546
|
+
* which Subagent role the viewed session's dispatch resolved, hovering as
|
|
4547
|
+
* `role → provider/model`.
|
|
4548
|
+
*
|
|
4549
|
+
* Contract notes (verified 2026-09-09 against the harness checkout):
|
|
4550
|
+
* - The slot is `kind: 'list'`, `scope: 'session'`, owner props an empty
|
|
4551
|
+
* marker (`ConversationHeaderActionOwnerProps`, `children?: never`) — the
|
|
4552
|
+
* header renders occupants with `renderSlot(..., {})`, so ALL data flows
|
|
4553
|
+
* through this component's inject face and the session standard kit.
|
|
4554
|
+
* - Every `scope: 'session'` occupant receives the session standard kit
|
|
4555
|
+
* (`sessionId` + `useSession` + `useProjection`; ui-session
|
|
4556
|
+
* `src/client/index.ts:112-119`, merged into the runtime share by ui-slots'
|
|
4557
|
+
* `PropsRuntime`) — the fetch keys off the `sessionId` prop directly (mount
|
|
4558
|
+
* + whenever the prop changes; the slot machinery remounts the occupant per
|
|
4559
|
+
* viewed session — no manual session subscription). The compiled peer types
|
|
4560
|
+
* do not carry the ui-session standard-props merge into this plugin's
|
|
4561
|
+
* typecheck program (that package is deliberately not a plugin peer), so
|
|
4562
|
+
* the seat is read structurally and guarded — a version-skewed host without
|
|
4563
|
+
* it renders nothing, never throws.
|
|
4564
|
+
* - Data: `fallbacks/subagent-roles` gateway readbacks via the injected fetch
|
|
4565
|
+
* face ({@link fetchSubagentRoleRecord} — never throws): one on mount +
|
|
4566
|
+
* whenever the viewed session changes, then a BOUNDED delayed re-probe
|
|
4567
|
+
* while no record has landed (the record is written at the subagent's first
|
|
4568
|
+
* dispatch request, which can land after this header mounted).
|
|
4569
|
+
* - Render-only discipline (C4 pattern, same as `ConversationFallbackSwitch`):
|
|
4570
|
+
* the badge contributes a view; no message construction, no model-context
|
|
4571
|
+
* injection. Degrade-never-crash: a missing record, an `inherit` role, or
|
|
4572
|
+
* ANY readback error renders `null` — the utilities strip collapses cleanly.
|
|
4573
|
+
*/
|
|
4574
|
+
/**
|
|
4575
|
+
* Bounded delayed re-probe (QC fix wave F-001): while the viewed session has
|
|
4576
|
+
* no record yet, re-fetch up to {@link ROLE_RECORD_PROBES} times
|
|
4577
|
+
* {@link ROLE_RECORD_PROBE_DELAY_MS} apart (~10s window) and stop on the
|
|
4578
|
+
* first record, a session switch, or unmount. The record is written once, at
|
|
4579
|
+
* the subagent's FIRST dispatch request — a header opened before that moment
|
|
4580
|
+
* would otherwise never see the badge until remount.
|
|
4581
|
+
*/
|
|
4582
|
+
const ROLE_RECORD_PROBE_DELAY_MS = 2e3;
|
|
4583
|
+
const ROLE_RECORD_PROBES = 5;
|
|
4584
|
+
/**
|
|
4585
|
+
* Render the viewed session's dispatch-resolved role badge.
|
|
4586
|
+
* @param props - composed slot props (the `sessionId` session-kit seat is
|
|
4587
|
+
* read structurally — see the module docblock).
|
|
4588
|
+
* @returns the badge element, or `null` when there is nothing to show.
|
|
4589
|
+
*/
|
|
4590
|
+
function SubagentRoleBadge(props) {
|
|
4591
|
+
const { t, controller } = props;
|
|
4592
|
+
const seatSessionId = props.sessionId;
|
|
4593
|
+
const sessionId = typeof seatSessionId === "string" && seatSessionId !== "" ? seatSessionId : void 0;
|
|
4594
|
+
const [stamped, setStamped] = (0, react.useState)({
|
|
4595
|
+
sessionId,
|
|
4596
|
+
record: void 0
|
|
4597
|
+
});
|
|
4598
|
+
if (stamped.sessionId !== sessionId) setStamped({
|
|
4599
|
+
sessionId,
|
|
4600
|
+
record: void 0
|
|
4601
|
+
});
|
|
4602
|
+
const record = stamped.sessionId === sessionId ? stamped.record : void 0;
|
|
4603
|
+
(0, react.useEffect)(() => {
|
|
4604
|
+
if (sessionId === void 0) return;
|
|
4605
|
+
let cancelled = false;
|
|
4606
|
+
let timer;
|
|
4607
|
+
const probe = (attempt) => {
|
|
4608
|
+
controller.fetchSubagentRole(sessionId).then((next) => {
|
|
4609
|
+
if (cancelled) return;
|
|
4610
|
+
if (next !== void 0) {
|
|
4611
|
+
setStamped({
|
|
4612
|
+
sessionId,
|
|
4613
|
+
record: next
|
|
4614
|
+
});
|
|
4615
|
+
return;
|
|
4616
|
+
}
|
|
4617
|
+
if (attempt >= ROLE_RECORD_PROBES) return;
|
|
4618
|
+
timer = setTimeout(() => {
|
|
4619
|
+
timer = void 0;
|
|
4620
|
+
probe(attempt + 1);
|
|
4621
|
+
}, ROLE_RECORD_PROBE_DELAY_MS);
|
|
4622
|
+
});
|
|
4623
|
+
};
|
|
4624
|
+
probe(0);
|
|
4625
|
+
return () => {
|
|
4626
|
+
cancelled = true;
|
|
4627
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
4628
|
+
};
|
|
4629
|
+
}, [controller, sessionId]);
|
|
4630
|
+
if (record === void 0 || record.role === "inherit") return null;
|
|
4631
|
+
const model = record.model === void 0 ? void 0 : `${record.model.provider}/${record.model.model}`;
|
|
4632
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4633
|
+
className: SubagentRoleBadge_module_css_default.badge,
|
|
4634
|
+
title: model === void 0 ? record.role : t("subagentRole.hover", {
|
|
4635
|
+
role: record.role,
|
|
4636
|
+
model
|
|
4637
|
+
}),
|
|
4638
|
+
children: record.role
|
|
4639
|
+
});
|
|
4640
|
+
}
|
|
4641
|
+
//#endregion
|
|
4478
4642
|
//#region src/client/index.ts
|
|
4479
4643
|
/**
|
|
4480
4644
|
* Required services (cordis fiber inject); registrations wait on the slot
|
|
@@ -4591,6 +4755,15 @@ window.__ModuleLoader__.load({
|
|
|
4591
4755
|
locale: NS
|
|
4592
4756
|
}, ConversationFallbackSwitch);
|
|
4593
4757
|
});
|
|
4758
|
+
ctx.slots.inject("conversation.session.header.utilities", function* () {
|
|
4759
|
+
yield ctx.slots.register({
|
|
4760
|
+
name: "conversation.session.header.utilities",
|
|
4761
|
+
id: "fallbacks-subagent-role",
|
|
4762
|
+
order: -20,
|
|
4763
|
+
locale: NS,
|
|
4764
|
+
inject: () => ({ controller })
|
|
4765
|
+
}, SubagentRoleBadge);
|
|
4766
|
+
});
|
|
4594
4767
|
}
|
|
4595
4768
|
//#endregion
|
|
4596
4769
|
exports.FALLBACKS_SETTINGS_NS = FALLBACKS_SETTINGS_NS;
|