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.
@@ -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 V4
406
- * model — Flash XOR Pro. Leading entries (the card's 默认降级链 block) are
407
- * the ordered walk before that last-resort fallback. An empty chain or a
408
- * chain whose tail is not an official V4 model keeps slot rows inert and
409
- * refuses the virtual-row override/delegate; the v0.2.2 failure walk over
410
- * the raw chain stays verbatim.
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 === "deepseek-official/deepseek-v4-flash" || tail === "deepseek-official/deepseek-v4-pro";
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. A non-array value resolves to `[]`; malformed entries are
531
- * dropped, so an all-bad array also lands `[]`. The store never trusts a
532
- * misshapen badge field.
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
- return value.filter((entry) => {
537
- if (!isRecord(entry)) return false;
538
- return typeof entry.id === "string" && typeof entry.overridden === "boolean";
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
- /** Seed-default persona from a revert-seed wire body (issue #59). */
592
- function revertOutcomePersona(value) {
593
- if (value === null || typeof value !== "object" || !("outcome" in value)) return void 0;
594
- const outcome = value.outcome;
595
- if (outcome === null || typeof outcome !== "object") return void 0;
596
- if (!("reverted" in outcome) || outcome.reverted !== true) return void 0;
597
- if (!("persona" in outcome) || typeof outcome.persona !== "string") return void 0;
598
- return outcome.persona;
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
- * Revert one seeded role to its CURRENT declared seed default (spec §9.4,
1224
- * AC-3) through the gateway channel (`/api/fallbacks/revert-seed`). Same
1225
- * write guards as {@link save} — writable / saving / write-generation —
1226
- * and the same KD-G3 error handling: any business rejection or transport
1227
- * failure surfaces its message in `state.error` for the error banner and
1228
- * the form stays editable for retry. A business `{ reverted: false,
1229
- * reason }` outcome is still a successful RPC — the post-write read
1230
- * result (config / legacyKeys / seeds) lands either way, and the revert
1231
- * button stays disabled while the write is in flight.
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
- async revertSeed(id) {
1241
- const state = this.store.getSnapshot();
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": "全天链的最后一档兜底:官方 V4 Flash 或 V4 Pro 二选一",
1461
- "allDay.flash": "官方 V4 Flash(deepseek-official/deepseek-v4-flash)",
1462
- "allDay.pro": "官方 V4 Pro(deepseek-official/deepseek-v4-pro)",
1463
- "allDay.nonconforming": "当前默认模型不合法:请选择官方 V4 Flash 或 V4 Pro 后保存",
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.seedDefault": "seed 默认",
1473
- "roles.seedOverride": "seed 覆盖",
1474
- "roles.revertPersona": "还原 Seed 默认",
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": "默认模型必须二选一:官方 V4 Flash 或 V4 Pro",
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 V4 Flash or Pro (pick exactly one)",
1653
- "allDay.flash": "Official V4 Flash (deepseek-official/deepseek-v4-flash)",
1654
- "allDay.pro": "Official V4 Pro (deepseek-official/deepseek-v4-pro)",
1655
- "allDay.nonconforming": "The current default model is not valid: pick official V4 Flash or Pro before saving",
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.seedDefault": "Seed default",
1665
- "roles.seedOverride": "Seed override",
1666
- "roles.revertPersona": "Revert to seed default",
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 V4 model (V4 Flash or V4 Pro)",
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$2 = "dsh-llm-fallbacks/FallbacksCard.module.css";
1784
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
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$2;
1788
- tag.textContent = css$2;
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 ALL_DAY_FLASH = "deepseek-official/deepseek-v4-flash";
1955
- const ALL_DAY_PRO = "deepseek-official/deepseek-v4-pro";
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 V4 id when the chain TAIL
2009
- * is that model (Flash XOR Pro — leading 默认降级链 entries allowed);
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 === ALL_DAY_FLASH || tail === ALL_DAY_PRO ? tail : "";
2048
+ return tail !== void 0 && isOfficialAllDayId(tail) ? tail : "";
2016
2049
  }
2017
2050
  /**
2018
- * The 默认降级链 editor row: the leading entries BEFORE the official-V4
2019
- * tail, or the whole chain while the tail is not official (the draft
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 V4 — Flash XOR
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
- * `seededIds` is the live trimmed-id → overridden map derived from
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 its persona edits must stay persistable); non-seeded
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, seededIds) {
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 && !seededIds.has(role.id.trim())) errors.sub.push(t("validation.roleChainRequired", { id: role.id }));
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 !== ALL_DAY_FLASH && allDayTail !== ALL_DAY_PRO) errors.main.push(t("validation.allDayRequired"));
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 || force || !mainDirty) {
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 || force || !subDirty) {
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 || force || !advancedDirty) setScalars((prev) => ({
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 seededIds = /* @__PURE__ */ new Map();
2670
- for (const seed of state.seeds) seededIds.set(seed.id.trim(), seed.overridden);
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, seededIds);
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, seededIds);
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
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3415
- className: FallbacksCard_module_css_default.optionRow,
3416
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
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 === ALL_DAY_PRO,
3432
- disabled: !writable,
3468
+ checked: allDayModel === id,
3469
+ disabled: !writable || id === "deepseek-official/deepseek-pro",
3433
3470
  onChange: () => {
3434
- setAllDayModel(ALL_DAY_PRO);
3471
+ setAllDayModel(id);
3435
3472
  }
3436
- }), t("allDay.pro")]
3437
- }),
3438
- allDayModel === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3439
- className: FallbacksCard_module_css_default.hint,
3440
- children: t("allDay.nonconforming")
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 = seededIds.get(row.id.trim());
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 || seed !== void 0,
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
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3601
- className: FallbacksCard_module_css_default.ruleCellLabel,
3602
- children: t("roles.persona")
3603
- }),
3604
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
3605
- rows: 3,
3606
- className: `${FallbacksCard_module_css_default.input} ${FallbacksCard_module_css_default.inputTextarea}`,
3607
- value: row.persona,
3608
- placeholder: t("roles.personaPlaceholder"),
3609
- "aria-label": t("roles.persona"),
3610
- disabled: !writable,
3611
- onChange: (event) => {
3612
- updateRoleRow(index, { persona: event.target.value });
3613
- }
3614
- }),
3615
- seed !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3616
- className: FallbacksCard_module_css_default.hint,
3617
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3618
- className: FallbacksCard_module_css_default.pending,
3619
- children: t(seed ? "roles.seedOverride" : "roles.seedDefault")
3620
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3621
- variant: "outline",
3622
- size: "sm",
3623
- disabled: !writable || saving,
3624
- onClick: () => {
3625
- forceReseed.current = true;
3626
- controller.revertSeed(row.id.trim()).then((persona) => {
3627
- if (persona === void 0) return;
3628
- updateRoleRow(index, { persona });
3629
- });
3630
- },
3631
- children: t("roles.revertPersona")
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$1 = "\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";
4216
- const tagId$1 = "dsh-llm-fallbacks/GeneralFallbacksRow.module.css";
4217
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
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$1;
4221
- tag.textContent = css$1;
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;