dsh-llm-fallbacks 0.6.2 → 0.6.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.
@@ -414,7 +414,7 @@ window.__ModuleLoader__.load({
414
414
  * `deepseek-v4-flash` and the never-served legacy
415
415
  * `deepseek-official/deepseek-pro` included) keeps slot rows inert and
416
416
  * refuses the virtual-row
417
- * delegate; the v0.2.2 failure walk over the raw chain stays
417
+ * delegate; the legacy failure walk over the raw chain stays
418
418
  * verbatim.
419
419
  */
420
420
  function isAllDayConforming(chain) {
@@ -432,7 +432,7 @@ window.__ModuleLoader__.load({
432
432
  * (`isAllDayConforming(config.rootChain)`) the winner is ALWAYS `'all-day'`
433
433
  * — a legacy multi-model (or empty) chain earns no slot rows, so every
434
434
  * surface fed by this resolver reports the inert state and routing stays on
435
- * the raw `rootChain` (the v0.2.2 walk verbatim).
435
+ * the raw `rootChain` (the legacy walk verbatim).
436
436
  */
437
437
  function resolveSlotState(config, now, tz) {
438
438
  if (!isAllDayConforming(config.rootChain)) return {
@@ -1109,7 +1109,7 @@ window.__ModuleLoader__.load({
1109
1109
  /**
1110
1110
  * Read the recent-switch summary for the current session (spec §2.5 D-5):
1111
1111
  * one tail page (`maxMessages` = {@link SWITCHES_HISTORY_PAGE}) read from
1112
- * the `session/follow` opening snapshot — 0.1.2 has no unary tail-page
1112
+ * the `session/follow` opening snapshot — the host has no unary tail-page
1113
1113
  * read (`session/page` needs the follow opening frame's cursor), so the
1114
1114
  * stream is cancelled right after its first frame —
1115
1115
  * `fallbacks/switch` events extracted newest-first capped at
@@ -1357,6 +1357,8 @@ window.__ModuleLoader__.load({
1357
1357
  "alwaysModeRetryCap.hint": "达到上限次数后切换;0 表示禁用",
1358
1358
  "alwaysModeRetryCap.tooltip": "retryPolicy 为 always 的模型在同一请求内重试达到该次数后切换;0 表示禁用。",
1359
1359
  "advanced.label": "高级选项",
1360
+ "advanced.expand": "展开高级选项",
1361
+ "advanced.collapse": "收起高级选项",
1360
1362
  "roleAutoMatch.label": "启用角色自动匹配",
1361
1363
  "roleAutoMatch.hint": "规则未命中时,由模型自选最贴近的已声明角色",
1362
1364
  "roleAutoMatch.tooltip": "规则未命中时,模型会自动从已声明角色(id + persona)中选择最匹配者并注入该角色的链;关闭后未命中规则时按现状回落(inherit / rootChain)。",
@@ -1542,6 +1544,8 @@ window.__ModuleLoader__.load({
1542
1544
  "alwaysModeRetryCap.hint": "Switches after the cap; 0 disables",
1543
1545
  "alwaysModeRetryCap.tooltip": "Models whose retryPolicy is always switch after this many retries within one request; 0 disables.",
1544
1546
  "advanced.label": "Advanced options",
1547
+ "advanced.expand": "Expand advanced options",
1548
+ "advanced.collapse": "Collapse advanced options",
1545
1549
  "roleAutoMatch.label": "Enable role auto-match",
1546
1550
  "roleAutoMatch.hint": "On rules-miss, the model picks the closest declared role",
1547
1551
  "roleAutoMatch.tooltip": "When no rule matches, the model auto-selects the best-fit declared role (id + persona) and uses its chain; turn off to keep today's fallback (inherit / rootChain) on a rules-miss.",
@@ -1738,7 +1742,7 @@ window.__ModuleLoader__.load({
1738
1742
  }
1739
1743
  //#endregion
1740
1744
  //#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/FallbacksCard.module.css.mjs
1741
- const css$3 = "\n\n\n._20fd0e45_root {\n min-width: 0;\n}\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._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._94c91bfd_fieldset {\n margin: 0;\n padding: 0;\n border: none;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n\n._ba240d82_sectionHeading {\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 display: block;\n min-width: 0;\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\n._94c91bfd_fieldset > ._67826267_field,\n._94c91bfd_fieldset > ._9998065c_checkboxRow,\n._94c91bfd_fieldset > ._3e95886d_numberFields {\n padding: 12px 0;\n}\n\n._94c91bfd_fieldset > ._67826267_field + ._67826267_field,\n._94c91bfd_fieldset > ._67826267_field + ._3e95886d_numberFields,\n._94c91bfd_fieldset > ._9998065c_checkboxRow + ._67826267_field {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n\n._94c91bfd_fieldset > ._9998065c_checkboxRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._13e68c3f_fieldLabel {\n \n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 0;\n font-size: 13px;\n line-height: 1.5;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\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._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._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 position: relative;\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._a6244318_infoHint::after {\n content: attr(data-tip);\n position: absolute;\n top: 50%;\n left: calc(100% + 8px);\n transform: translateY(-50%);\n z-index: 10;\n box-sizing: border-box;\n width: max-content;\n max-width: 280px;\n padding: 5px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n font-size: 11px;\n line-height: 17px;\n font-weight: 400;\n white-space: normal;\n text-align: left;\n pointer-events: none;\n opacity: 0;\n transition: opacity .12s;\n}\n\n._a6244318_infoHint:hover::after,\n._a6244318_infoHint:focus-visible::after {\n opacity: 1;\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: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-md);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n}\n\n._f9d86f7b_input:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-state-business-primary);\n}\n\n._f9d86f7b_input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n._f9d86f7b_input:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n\n\n._3a9b42fd_inputTextarea {\n height: auto;\n min-height: 72px;\n padding: 8px 12px;\n resize: vertical;\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-visible {\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: 12px;\n}\n\n._3e95886d_numberFields ._67826267_field {\n padding: 0;\n}\n\n._0cfb5881_list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n\n._f5c620d6_editorCard {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n}\n\n._224b1387_cardFoot {\n display: flex;\n justify-content: flex-end;\n}\n\n._8e220e07_ruleGrid {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n._24a12a2f_ruleCell {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 120px;\n flex: 1;\n}\n\n._1014c097_ruleCellLabel {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._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._cf3961bb_chevronFlip {\n transform: rotate(180deg);\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\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\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._711248a9_outlineButton {\n appearance: none;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-md);\n background: none;\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n._711248a9_outlineButton:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n._711248a9_outlineButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._711248a9_outlineButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\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._114985b2_footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding-top: 16px;\n}\n\n\n._f0864181_discard,\n._ccff7e48_save {\n appearance: none;\n border: 1px solid transparent;\n border-radius: var(--dsw-radius-md);\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n}\n\n._f0864181_discard {\n border-color: var(--dsw-alias-border-l2);\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n\n._f0864181_discard:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n._ccff7e48_save {\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n\n._f0864181_discard:disabled,\n._ccff7e48_save:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._f0864181_discard:focus-visible,\n._ccff7e48_save:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\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._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 ._a6244318_infoHint::after {\n transition: none;\n }\n\n ._631094a0_chevron {\n transition: none;\n }\n}\n";
1745
+ const css$3 = "\n\n\n._20fd0e45_root {\n min-width: 0;\n}\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._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._94c91bfd_fieldset {\n margin: 0;\n padding: 0;\n border: none;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n\n._ba240d82_sectionHeading {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n padding: 4px 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n._ddbc1b49_sectionHeadingText {\n display: block;\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._c41f9db7_sectionActions ._f0864181_discard,\n._c41f9db7_sectionActions ._ccff7e48_save {\n padding: 3px 12px;\n font-size: 12px;\n line-height: 18px;\n}\n\n\n._b116c758_sectionToggle {\n appearance: none;\n border: 0;\n background: none;\n display: flex;\n align-items: center;\n gap: 4px;\n margin: 0;\n padding: 0;\n font: inherit;\n color: inherit;\n cursor: pointer;\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: 1px;\n}\n\n\n._80101203_advancedBody {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n._94c91bfd_fieldset > ._80101203_advancedBody > ._67826267_field,\n._94c91bfd_fieldset > ._80101203_advancedBody > ._9998065c_checkboxRow,\n._94c91bfd_fieldset > ._80101203_advancedBody > ._3e95886d_numberFields {\n padding: 12px 0;\n}\n\n._94c91bfd_fieldset > ._80101203_advancedBody > ._67826267_field + ._67826267_field,\n._94c91bfd_fieldset > ._80101203_advancedBody > ._9998065c_checkboxRow + ._67826267_field,\n._94c91bfd_fieldset > ._80101203_advancedBody > ._67826267_field + ._3e95886d_numberFields {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\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\n._94c91bfd_fieldset > ._67826267_field,\n._94c91bfd_fieldset > ._9998065c_checkboxRow,\n._94c91bfd_fieldset > ._3e95886d_numberFields {\n padding: 12px 0;\n}\n\n._94c91bfd_fieldset > ._67826267_field + ._67826267_field,\n._94c91bfd_fieldset > ._67826267_field + ._3e95886d_numberFields,\n._94c91bfd_fieldset > ._9998065c_checkboxRow + ._67826267_field {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n\n._9998065c_checkboxRow {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n\n._9998065c_checkboxRow ._06389b18_checkbox {\n margin-top: 3px;\n}\n\n._13e68c3f_fieldLabel {\n \n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 0;\n font-size: 13px;\n line-height: 1.5;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\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\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._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 position: relative;\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._a6244318_infoHint::after {\n content: attr(data-tip);\n position: absolute;\n top: 50%;\n left: calc(100% + 8px);\n transform: translateY(-50%);\n z-index: 10;\n box-sizing: border-box;\n width: max-content;\n max-width: 280px;\n padding: 5px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n font-size: 11px;\n line-height: 17px;\n font-weight: 400;\n white-space: normal;\n text-align: left;\n pointer-events: none;\n opacity: 0;\n transition: opacity .12s;\n}\n\n._a6244318_infoHint:hover::after,\n._a6244318_infoHint:focus-visible::after {\n opacity: 1;\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: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-md);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n}\n\n._f9d86f7b_input:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-state-business-primary);\n}\n\n._f9d86f7b_input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n._f9d86f7b_input:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n\n\n._3a9b42fd_inputTextarea {\n height: auto;\n min-height: 72px;\n padding: 8px 12px;\n resize: vertical;\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-visible {\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: 12px;\n}\n\n._3e95886d_numberFields ._67826267_field {\n padding: 0;\n}\n\n._0cfb5881_list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n\n._f5c620d6_editorCard {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n}\n\n._224b1387_cardFoot {\n display: flex;\n justify-content: flex-end;\n}\n\n._8e220e07_ruleGrid {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n._24a12a2f_ruleCell {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 120px;\n flex: 1;\n}\n\n._1014c097_ruleCellLabel {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._631094a0_chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transform: rotate(-90deg);\n transition: transform .16s;\n}\n\n._44836ce8_chevronOpen {\n transform: none;\n}\n\n\n._cf3961bb_chevronFlip {\n transform: rotate(180deg);\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\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\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._711248a9_outlineButton {\n appearance: none;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-md);\n background: none;\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n._711248a9_outlineButton:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n._711248a9_outlineButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._711248a9_outlineButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\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._f0864181_discard,\n._ccff7e48_save {\n appearance: none;\n border: 1px solid transparent;\n border-radius: var(--dsw-radius-md);\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n}\n\n._f0864181_discard {\n border-color: var(--dsw-alias-border-l2);\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n\n._f0864181_discard:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n._ccff7e48_save {\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n\n._f0864181_discard:disabled,\n._ccff7e48_save:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._f0864181_discard:focus-visible,\n._ccff7e48_save:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\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._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 ._a6244318_infoHint::after {\n transition: none;\n }\n\n ._631094a0_chevron {\n transition: none;\n }\n}\n";
1742
1746
  const tagId$3 = "dsh-llm-fallbacks/FallbacksCard.module.css";
1743
1747
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1744
1748
  const tag = document.createElement("style");
@@ -1757,16 +1761,20 @@ window.__ModuleLoader__.load({
1757
1761
  "fieldset": "_94c91bfd_fieldset",
1758
1762
  "sectionHeading": "_ba240d82_sectionHeading",
1759
1763
  "sectionHeadingText": "_ddbc1b49_sectionHeadingText",
1764
+ "sectionActions": "_c41f9db7_sectionActions",
1765
+ "discard": "_f0864181_discard",
1766
+ "save": "_ccff7e48_save",
1767
+ "sectionToggle": "_b116c758_sectionToggle",
1768
+ "advancedBody": "_80101203_advancedBody",
1760
1769
  "field": "_67826267_field",
1761
1770
  "checkboxRow": "_9998065c_checkboxRow",
1762
1771
  "numberFields": "_3e95886d_numberFields",
1772
+ "checkbox": "_06389b18_checkbox",
1763
1773
  "fieldLabel": "_13e68c3f_fieldLabel",
1764
1774
  "hint": "_4bc809b8_hint",
1765
- "defaultNote": "_579f813a_defaultNote",
1766
1775
  "checkLabel": "_02c2f6df_checkLabel",
1767
1776
  "checkLabelTitle": "_f2d47237_checkLabelTitle",
1768
1777
  "checkLabelDesc": "_c1bed8ea_checkLabelDesc",
1769
- "checkbox": "_06389b18_checkbox",
1770
1778
  "slotPresetName": "_b1962759_slotPresetName",
1771
1779
  "infoHint": "_a6244318_infoHint",
1772
1780
  "infoHintDisabled": "_e655c840_infoHintDisabled",
@@ -1810,9 +1818,6 @@ window.__ModuleLoader__.load({
1810
1818
  "addButton": "_28202c90_addButton",
1811
1819
  "slotAddRow": "_6a2bd54c_slotAddRow",
1812
1820
  "rowActions": "_4e77523e_rowActions",
1813
- "footer": "_114985b2_footer",
1814
- "discard": "_f0864181_discard",
1815
- "save": "_ccff7e48_save",
1816
1821
  "statusBlock": "_fbd045e0_statusBlock",
1817
1822
  "statusTitle": "_d4f70367_statusTitle",
1818
1823
  "statusLine": "_8ab300ed_statusLine",
@@ -1837,11 +1842,13 @@ window.__ModuleLoader__.load({
1837
1842
  * rotating chevron, no dirty "unsaved" pill, no card-local open state, no
1838
1843
  * bordered `<li>` box. The page already renders the plugin title/description
1839
1844
  * above the card (the `locale/*.json` meta files the host resolves per UI
1840
- * language), so the notices, the form, and the footer tile directly beneath
1841
- * it in the official flat settings-form language (reference §3): fields at
1845
+ * language), so the notices, the form, and the section actions directly
1846
+ * beneath it in the official flat settings-form language (reference §3):
1847
+ * fields at
1842
1848
  * 12px vertical padding with 0.5px hairline separators, 34px inputs on the
1843
- * 0.5px l4 border, one dark solid Save footer. The card is ALWAYS open —
1844
- * nothing is hidden, so nothing needs disclosure state; the degraded /
1849
+ * 0.5px l4 border, per-section Discard + Save pairs on the section
1850
+ * headings. The card is ALWAYS open —
1851
+ * nothing needs card-level disclosure state; the degraded /
1845
1852
  * error / read-only / migration notices render flat atop the form (the
1846
1853
  * unavailable notice stays always-visible per KD-G5 — the documented
1847
1854
  * divergence from the advisor, whose unavailable card renders nothing: the
@@ -1853,19 +1860,22 @@ window.__ModuleLoader__.load({
1853
1860
  * unconditionally; the Plugins-page row toggle is the master switch and the
1854
1861
  * runtime gates read content presence (`isFallbackActive`).
1855
1862
  *
1856
- * ONE Save replaces the per-section saves (T3): the per-section split
1857
- * existed so one section's Save could not ride along another section's
1858
- * unsaved edits (PR #62 UX round 3) — with ONE save over ONE document that
1859
- * concern is moot. The footer's Save writes the whole validated draft
1860
- * (disabled = `!dirty || invalid || saving || !writable` — `invalid` is the
1861
- * LIVE whole-form `validateDraft` verdict plus the empty-rule-row check;
1862
- * section bucketing survives for ERROR PLACEMENT only: each violation
1863
- * renders under its owning section heading). Save additionally carries
1864
- * `!writable` (W-1, qc2 fix wave: the dirty-implies-writable assumption
1865
- * does not hold for this in-place-draft store). Discard is kept — our
1866
- * staged edits survive refresh, the advisor's documented divergence from
1867
- * the official no-discard form — a pure client-side revert of the WHOLE
1868
- * draft to the last accepted config (`!dirty || saving`).
1863
+ * PER-SECTION Save/Discard return beside each section heading (plan
1864
+ * fallbacks-card-section-ux, the maintainer's live-host feedback reversing
1865
+ * the flat plan's one-document model): the scroll-to-save cost of ONE
1866
+ * bottom Save outweighed it. Each section's Save writes ONLY that section's
1867
+ * fields (patch = the last ACCEPTED config with the section's fields
1868
+ * replaced — the ride-along protection, PR #62 UX round 3), gated by that
1869
+ * section's dirty term and validation bucket only (KD-U1: save =
1870
+ * `!sectionDirty || saving || !writable`, discard = `!sectionDirty ||
1871
+ * saving`; Save additionally carries `!writable` — W-1, qc2 fix wave: the
1872
+ * dirty-implies-writable assumption does not hold for this in-place-draft
1873
+ * store). Violations render live under their OWNING section heading, and a
1874
+ * store write failure renders under the section whose Save was last
1875
+ * clicked (`lastSaveSection`). Discard is kept — our staged edits survive
1876
+ * refresh, the advisor's documented divergence from the official
1877
+ * no-discard form — a pure client-side revert of THAT section's editors to
1878
+ * the last accepted config.
1869
1879
  *
1870
1880
  * The form body is the two-block editing surface (spec §8): the 6 top-level
1871
1881
  * scalar fields (trigger codes / revert policy / three numeric fields), the
@@ -1877,7 +1887,9 @@ window.__ModuleLoader__.load({
1877
1887
  * the time-slot row cards and the role entity cards (with the seeded
1878
1888
  * persona briefs) stay collapsible — a read-only view forces them open so
1879
1889
  * the configs stay reachable. The 主代理 / 子代理 / 高级选项 group labels
1880
- * stay as flat, non-collapsible section headings.
1890
+ * are semantic `<h2>` headings (T1); 高级选项 is a content-level disclosure
1891
+ * collapsed by default (T3 — same expand/collapse contract as the rows, a
1892
+ * read-only view forces it open).
1881
1893
  *
1882
1894
  * Validation: id format/reserved word/duplicates, undeclared rule role
1883
1895
  * references, illegal selectors, and a role with no chain entries (no model
@@ -2152,9 +2164,10 @@ window.__ModuleLoader__.load({
2152
2164
  * timeSlots / slot* / tz / default model / default chain; 子代理: role* /
2153
2165
  * rule*; 高级选项: trigger / cooldown / revert / always / roleAutoMatch —
2154
2166
  * the scalars are never validated, so the advanced bucket stays empty
2155
- * today). A non-empty result is the Save disabled gate's `invalid` term —
2156
- * the draft is never written while any bucket is non-empty. `persona` is
2157
- * free text and never validated.
2167
+ * today). A non-empty bucket blocks THAT section's Save write only
2168
+ * (per-section saves, plan fallbacks-card-section-ux) — a sibling section
2169
+ * with a clean bucket still saves. `persona` is free text and never
2170
+ * validated.
2158
2171
  *
2159
2172
  * `seedInfo` is the live trimmed-id → seed-entry map derived from
2160
2173
  * `state.seeds` (spec §9.4): the empty-chain block relaxes for seeded ids
@@ -2429,8 +2442,8 @@ window.__ModuleLoader__.load({
2429
2442
  }
2430
2443
  /**
2431
2444
  * Render the Fallbacks settings card inside the plugin-config section —
2432
- * flat: the notices, the form, and the footer tile directly under the
2433
- * page's plugin title/description, with no chrome of our own.
2445
+ * flat: the notices, the form, and the section action pairs directly under
2446
+ * the page's plugin title/description, with no chrome of our own.
2434
2447
  * @param props - slot-delivered injected dependencies and the synthesized t seat.
2435
2448
  * @returns the card.
2436
2449
  */
@@ -2449,6 +2462,8 @@ window.__ModuleLoader__.load({
2449
2462
  const [roleRows, setRoleRows] = (0, react.useState)(() => rolesToRows(defaultFallbacksConfig.roles.list));
2450
2463
  const [ruleRows, setRuleRows] = (0, react.useState)(() => rulesToRows(defaultFallbacksConfig.roles.rules));
2451
2464
  const [presetToAdd, setPresetToAdd] = (0, react.useState)("");
2465
+ const [lastSaveSection, setLastSaveSection] = (0, react.useState)(null);
2466
+ const [advancedOpen, setAdvancedOpen] = (0, react.useState)(false);
2452
2467
  const seededConfigKey = (0, react.useRef)(null);
2453
2468
  const draft = assembleConfig(scalars, allDayModel, state.config.rootChain, allDayChainRow, roleRows, ruleRows, state.config.roles.list, state.config.presets, scalars.roleAutoMatch, timeSlotRows);
2454
2469
  const hasEmptyRuleRows = ruleRows.some((row) => row.role === "");
@@ -2469,7 +2484,6 @@ window.__ModuleLoader__.load({
2469
2484
  state.config.alwaysModeRetryCap,
2470
2485
  state.config.roleAutoMatch
2471
2486
  ]);
2472
- const dirty = mainDirty || subDirty || advancedDirty;
2473
2487
  const firstSeedDone = (0, react.useRef)(false);
2474
2488
  (0, react.useEffect)(() => {
2475
2489
  if (state.status !== "ready") return;
@@ -2699,6 +2713,10 @@ window.__ModuleLoader__.load({
2699
2713
  };
2700
2714
  const saving = state.status === "saving";
2701
2715
  const writable = state.writable;
2716
+ const advancedVisible = advancedOpen || !writable;
2717
+ const cooldownMsTip = `${t("cooldownMs.tooltip")} ${t("defaults.prefix")}: ${defaultFallbacksConfig.cooldownMs}`;
2718
+ const maxSwitchesPerStepTip = `${t("maxSwitchesPerStep.tooltip")} ${t("defaults.prefix")}: ${defaultFallbacksConfig.maxSwitchesPerStep}`;
2719
+ const alwaysModeRetryCapTip = `${t("alwaysModeRetryCap.tooltip")} ${t("defaults.prefix")}: ${defaultFallbacksConfig.alwaysModeRetryCap}`;
2702
2720
  const unknownCodes = scalars.triggerCodes.filter((code) => !KNOWN_TRIGGER_CODES.includes(code));
2703
2721
  const presetsPresent = timeSlotRows.some((row) => row.kind === "preset");
2704
2722
  const glmConfigured = state.configuredProviders.some((entry) => entry.provider === "zai-coding-cn");
@@ -2713,7 +2731,6 @@ window.__ModuleLoader__.load({
2713
2731
  source: seed.source
2714
2732
  });
2715
2733
  const liveErrors = validateDraft(draft, t, seedInfo);
2716
- const invalid = hasEmptyRuleRows || liveErrors.main.length > 0 || liveErrors.sub.length > 0 || liveErrors.advanced.length > 0;
2717
2734
  const latestSwitch = state.switches[0];
2718
2735
  let switchesLine;
2719
2736
  if (state.switchesStatus === "error") switchesLine = t("status.switches.error", { message: state.switchesError });
@@ -2762,18 +2779,65 @@ window.__ModuleLoader__.load({
2762
2779
  mainDirty,
2763
2780
  subDirty
2764
2781
  ]);
2765
- const save = () => {
2766
- controller.save(draft);
2782
+ const sectionPatch = (section) => {
2783
+ const base = { ...state.config };
2784
+ switch (section) {
2785
+ case "main": return {
2786
+ ...base,
2787
+ rootChain: draft.rootChain,
2788
+ timeSlots: draft.timeSlots,
2789
+ tz: draft.tz
2790
+ };
2791
+ case "sub": return {
2792
+ ...base,
2793
+ roles: draft.roles
2794
+ };
2795
+ case "advanced": return {
2796
+ ...base,
2797
+ triggerCodes: draft.triggerCodes,
2798
+ cooldownMs: draft.cooldownMs,
2799
+ revertPolicy: draft.revertPolicy,
2800
+ maxSwitchesPerStep: draft.maxSwitchesPerStep,
2801
+ alwaysModeRetryCap: draft.alwaysModeRetryCap,
2802
+ roleAutoMatch: draft.roleAutoMatch
2803
+ };
2804
+ }
2805
+ };
2806
+ const saveSection = (section) => {
2807
+ if (liveErrors[section].length > 0 || section === "sub" && hasEmptyRuleRows) return;
2808
+ setLastSaveSection(section);
2809
+ controller.save(sectionPatch(section));
2767
2810
  };
2768
- const discard = () => {
2811
+ const discardSection = (section) => {
2769
2812
  const catalog = catalogOf(state);
2770
- setAllDayModel(allDayModelOf(state.config.rootChain));
2771
- setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalog));
2772
- setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalog));
2773
- setRoleRows(rolesToRows(state.config.roles.list, catalog));
2774
- setRuleRows(rulesToRows(state.config.roles.rules, catalog));
2775
- setScalars(scalarsOf(state.config));
2813
+ switch (section) {
2814
+ case "main":
2815
+ setAllDayModel(allDayModelOf(state.config.rootChain));
2816
+ setAllDayChainRow(allDayChainRowOf(state.config.rootChain, catalog));
2817
+ setTimeSlotRows(timeSlotsToRows(state.config.timeSlots ?? [], catalog));
2818
+ setScalars((prev) => ({
2819
+ ...prev,
2820
+ tz: state.config.tz ?? "Asia/Shanghai"
2821
+ }));
2822
+ break;
2823
+ case "sub":
2824
+ setRoleRows(rolesToRows(state.config.roles.list, catalog));
2825
+ setRuleRows(rulesToRows(state.config.roles.rules, catalog));
2826
+ break;
2827
+ case "advanced": setScalars((prev) => ({
2828
+ ...prev,
2829
+ triggerCodes: [...state.config.triggerCodes],
2830
+ cooldownMs: state.config.cooldownMs,
2831
+ revertPolicy: state.config.revertPolicy,
2832
+ maxSwitchesPerStep: state.config.maxSwitchesPerStep,
2833
+ alwaysModeRetryCap: state.config.alwaysModeRetryCap,
2834
+ roleAutoMatch: state.config.roleAutoMatch
2835
+ }));
2836
+ }
2776
2837
  };
2838
+ (0, react.useEffect)(() => {
2839
+ if (state.status === "ready") setLastSaveSection(null);
2840
+ }, [state.status]);
2777
2841
  const degradedLatch = (0, react.useRef)(false);
2778
2842
  if (state.status === "ready") degradedLatch.current = !state.present;
2779
2843
  const degraded = state.status === "ready" ? !state.present : degradedLatch.current;
@@ -2785,7 +2849,7 @@ window.__ModuleLoader__.load({
2785
2849
  role: "status",
2786
2850
  children: t("legacy.banner", { keys: state.legacyKeys.join(", ") })
2787
2851
  }),
2788
- state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2852
+ state.status === "error" && state.error !== null && lastSaveSection === null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2789
2853
  className: FallbacksCard_module_css_default.noticeRow,
2790
2854
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2791
2855
  className: FallbacksCard_module_css_default.error,
@@ -2814,19 +2878,44 @@ window.__ModuleLoader__.load({
2814
2878
  className: FallbacksCard_module_css_default.fieldset,
2815
2879
  disabled: !writable,
2816
2880
  children: [
2817
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2881
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
2818
2882
  className: FallbacksCard_module_css_default.sectionHeading,
2819
2883
  id: "fallbacks-main-agent",
2820
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2884
+ "aria-label": t("mainAgent.label"),
2885
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2821
2886
  className: FallbacksCard_module_css_default.sectionHeadingText,
2822
2887
  children: t("mainAgent.label")
2823
- })
2888
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2889
+ className: FallbacksCard_module_css_default.sectionActions,
2890
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2891
+ type: "button",
2892
+ className: FallbacksCard_module_css_default.discard,
2893
+ disabled: !mainDirty || saving,
2894
+ onClick: () => {
2895
+ discardSection("main");
2896
+ },
2897
+ children: t("discard")
2898
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2899
+ type: "button",
2900
+ className: FallbacksCard_module_css_default.save,
2901
+ disabled: !writable || saving || !mainDirty,
2902
+ onClick: () => {
2903
+ saveSection("main");
2904
+ },
2905
+ children: saving ? t("save.saving") : t("save")
2906
+ })]
2907
+ })]
2824
2908
  }),
2825
2909
  liveErrors.main.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2826
2910
  className: FallbacksCard_module_css_default.error,
2827
2911
  role: "alert",
2828
2912
  children: `${t("validation.blocked")}${liveErrors.main.join("; ")}`
2829
2913
  }),
2914
+ lastSaveSection === "main" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2915
+ className: FallbacksCard_module_css_default.error,
2916
+ role: "alert",
2917
+ children: t("error.generic", { message: state.error })
2918
+ }),
2830
2919
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2831
2920
  className: FallbacksCard_module_css_default.field,
2832
2921
  role: "group",
@@ -3254,19 +3343,44 @@ window.__ModuleLoader__.load({
3254
3343
  })
3255
3344
  ]
3256
3345
  }),
3257
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3346
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
3258
3347
  className: FallbacksCard_module_css_default.sectionHeading,
3259
3348
  id: "fallbacks-subagents",
3260
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3349
+ "aria-label": t("subagents.label"),
3350
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3261
3351
  className: FallbacksCard_module_css_default.sectionHeadingText,
3262
3352
  children: t("subagents.label")
3263
- })
3353
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3354
+ className: FallbacksCard_module_css_default.sectionActions,
3355
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3356
+ type: "button",
3357
+ className: FallbacksCard_module_css_default.discard,
3358
+ disabled: !subDirty || saving,
3359
+ onClick: () => {
3360
+ discardSection("sub");
3361
+ },
3362
+ children: t("discard")
3363
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3364
+ type: "button",
3365
+ className: FallbacksCard_module_css_default.save,
3366
+ disabled: !writable || saving || !subDirty,
3367
+ onClick: () => {
3368
+ saveSection("sub");
3369
+ },
3370
+ children: saving ? t("save.saving") : t("save")
3371
+ })]
3372
+ })]
3264
3373
  }),
3265
3374
  liveErrors.sub.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3266
3375
  className: FallbacksCard_module_css_default.error,
3267
3376
  role: "alert",
3268
3377
  children: `${t("validation.blocked")}${liveErrors.sub.join("; ")}`
3269
3378
  }),
3379
+ lastSaveSection === "sub" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3380
+ className: FallbacksCard_module_css_default.error,
3381
+ role: "alert",
3382
+ children: t("error.generic", { message: state.error })
3383
+ }),
3270
3384
  state.subagentPolicy?.state === "enabled" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3271
3385
  className: FallbacksCard_module_css_default.policyStatus,
3272
3386
  role: "status",
@@ -3692,272 +3806,267 @@ window.__ModuleLoader__.load({
3692
3806
  })
3693
3807
  ]
3694
3808
  }),
3695
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3809
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
3696
3810
  className: FallbacksCard_module_css_default.sectionHeading,
3697
3811
  id: "fallbacks-advanced",
3698
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3699
- className: FallbacksCard_module_css_default.sectionHeadingText,
3700
- children: t("advanced.label")
3701
- })
3702
- }),
3703
- liveErrors.advanced.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3704
- className: FallbacksCard_module_css_default.error,
3705
- role: "alert",
3706
- children: `${t("validation.blocked")}${liveErrors.advanced.join("; ")}`
3707
- }),
3708
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3709
- className: FallbacksCard_module_css_default.checkboxRow,
3710
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3711
- className: FallbacksCard_module_css_default.checkLabel,
3712
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3713
- className: FallbacksCard_module_css_default.checkLabelTitle,
3714
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3715
- htmlFor: "fallbacks-role-automatch",
3716
- children: t("roleAutoMatch.label")
3717
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3718
- label: t("roleAutoMatch.tooltip"),
3719
- disabled: !writable
3720
- })]
3721
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3722
- className: FallbacksCard_module_css_default.checkLabelDesc,
3723
- children: t("roleAutoMatch.hint")
3724
- })]
3725
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3726
- id: "fallbacks-role-automatch",
3727
- type: "checkbox",
3728
- className: FallbacksCard_module_css_default.checkbox,
3729
- checked: scalars.roleAutoMatch,
3812
+ "aria-label": t("advanced.label"),
3813
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3814
+ type: "button",
3815
+ className: FallbacksCard_module_css_default.sectionToggle,
3730
3816
  disabled: !writable,
3731
- onChange: (event) => {
3732
- updateScalars((draft) => {
3733
- draft.roleAutoMatch = event.target.checked;
3734
- });
3735
- }
3736
- })]
3817
+ "aria-expanded": advancedVisible,
3818
+ "aria-controls": advancedVisible ? "fallbacks-advanced-body" : void 0,
3819
+ "aria-label": t(advancedVisible ? "advanced.collapse" : "advanced.expand"),
3820
+ onClick: () => {
3821
+ if (writable) setAdvancedOpen(!advancedOpen);
3822
+ },
3823
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDownIcon, { className: advancedVisible ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3824
+ className: FallbacksCard_module_css_default.sectionHeadingText,
3825
+ children: t("advanced.label")
3826
+ })]
3827
+ })
3737
3828
  }),
3738
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3739
- className: FallbacksCard_module_css_default.field,
3740
- role: "group",
3741
- "aria-labelledby": "fallbacks-trigger-codes",
3829
+ advancedVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3830
+ id: "fallbacks-advanced-body",
3831
+ className: FallbacksCard_module_css_default.advancedBody,
3742
3832
  children: [
3743
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3744
- className: FallbacksCard_module_css_default.fieldLabel,
3745
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3746
- id: "fallbacks-trigger-codes",
3747
- children: t("triggerCodes.label")
3748
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3749
- label: t("triggerCodes.tooltip"),
3750
- disabled: !writable
3751
- })]
3833
+ liveErrors.advanced.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3834
+ className: FallbacksCard_module_css_default.error,
3835
+ role: "alert",
3836
+ children: `${t("validation.blocked")}${liveErrors.advanced.join("; ")}`
3752
3837
  }),
3753
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3754
- className: FallbacksCard_module_css_default.hint,
3755
- children: t("triggerCodes.hint")
3838
+ lastSaveSection === "advanced" && state.status === "error" && state.error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3839
+ className: FallbacksCard_module_css_default.error,
3840
+ role: "alert",
3841
+ children: t("error.generic", { message: state.error })
3756
3842
  }),
3757
- KNOWN_TRIGGER_CODES.map((code) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3758
- className: FallbacksCard_module_css_default.optionRow,
3843
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3844
+ className: FallbacksCard_module_css_default.checkboxRow,
3759
3845
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3846
+ id: "fallbacks-role-automatch",
3760
3847
  type: "checkbox",
3761
- checked: scalars.triggerCodes.includes(code),
3848
+ className: FallbacksCard_module_css_default.checkbox,
3849
+ checked: scalars.roleAutoMatch,
3850
+ disabled: !writable,
3762
3851
  onChange: (event) => {
3763
3852
  updateScalars((draft) => {
3764
- draft.triggerCodes = withTriggerCode(draft.triggerCodes, code, event.target.checked);
3853
+ draft.roleAutoMatch = event.target.checked;
3765
3854
  });
3766
3855
  }
3767
- }), t(TRIGGER_CODE_LABELS[code])]
3768
- }, code)),
3769
- unknownCodes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3770
- className: FallbacksCard_module_css_default.hint,
3771
- children: t("triggerCodes.extra", { codes: unknownCodes.join(", ") })
3772
- })
3773
- ]
3774
- }),
3775
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3776
- className: FallbacksCard_module_css_default.field,
3777
- role: "group",
3778
- "aria-labelledby": "fallbacks-revert-policy",
3779
- children: [
3780
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3781
- className: FallbacksCard_module_css_default.fieldLabel,
3782
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3783
- id: "fallbacks-revert-policy",
3784
- children: t("revertPolicy.label")
3785
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3786
- label: t("revertPolicy.tooltip"),
3787
- disabled: !writable
3856
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3857
+ className: FallbacksCard_module_css_default.checkLabel,
3858
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3859
+ className: FallbacksCard_module_css_default.checkLabelTitle,
3860
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3861
+ htmlFor: "fallbacks-role-automatch",
3862
+ children: t("roleAutoMatch.label")
3863
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3864
+ label: t("roleAutoMatch.tooltip"),
3865
+ disabled: !writable
3866
+ })]
3867
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3868
+ className: FallbacksCard_module_css_default.checkLabelDesc,
3869
+ htmlFor: "fallbacks-role-automatch",
3870
+ children: t("roleAutoMatch.hint")
3871
+ })]
3788
3872
  })]
3789
3873
  }),
3790
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3791
- className: FallbacksCard_module_css_default.hint,
3792
- children: t("revertPolicy.hint")
3793
- }),
3794
- ["cooldown-expiry", "never"].map((policy) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3795
- className: FallbacksCard_module_css_default.optionRow,
3796
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3797
- type: "radio",
3798
- name: "fallbacks-revert-policy",
3799
- checked: scalars.revertPolicy === policy,
3800
- onChange: () => {
3801
- updateScalars((draft) => {
3802
- draft.revertPolicy = policy;
3803
- });
3804
- }
3805
- }), t(`revertPolicy.${policy}`)]
3806
- }, policy))
3807
- ]
3808
- }),
3809
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3810
- className: FallbacksCard_module_css_default.numberFields,
3811
- children: [
3812
3874
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3813
3875
  className: FallbacksCard_module_css_default.field,
3876
+ role: "group",
3877
+ "aria-labelledby": "fallbacks-trigger-codes",
3814
3878
  children: [
3815
3879
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3816
3880
  className: FallbacksCard_module_css_default.fieldLabel,
3817
- children: [
3818
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3819
- htmlFor: "fallbacks-cooldown-ms",
3820
- children: t("cooldownMs.label")
3821
- }),
3822
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3823
- label: t("cooldownMs.tooltip"),
3824
- disabled: !writable
3825
- }),
3826
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3827
- className: FallbacksCard_module_css_default.defaultNote,
3828
- children: [
3829
- t("defaults.prefix"),
3830
- ": ",
3831
- state.config.cooldownMs
3832
- ]
3833
- })
3834
- ]
3835
- }),
3836
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3837
- id: "fallbacks-cooldown-ms",
3838
- className: FallbacksCard_module_css_default.input,
3839
- type: "number",
3840
- min: 0,
3841
- value: String(scalars.cooldownMs),
3842
- disabled: !writable,
3843
- onChange: (event) => {
3844
- updateScalars((draft) => {
3845
- draft.cooldownMs = parseCount(event.target.value);
3846
- });
3847
- }
3881
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3882
+ id: "fallbacks-trigger-codes",
3883
+ children: t("triggerCodes.label")
3884
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3885
+ label: t("triggerCodes.tooltip"),
3886
+ disabled: !writable
3887
+ })]
3848
3888
  }),
3849
3889
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3850
3890
  className: FallbacksCard_module_css_default.hint,
3851
- children: t("cooldownMs.hint")
3891
+ children: t("triggerCodes.hint")
3892
+ }),
3893
+ KNOWN_TRIGGER_CODES.map((code) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3894
+ className: FallbacksCard_module_css_default.optionRow,
3895
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3896
+ type: "checkbox",
3897
+ checked: scalars.triggerCodes.includes(code),
3898
+ onChange: (event) => {
3899
+ updateScalars((draft) => {
3900
+ draft.triggerCodes = withTriggerCode(draft.triggerCodes, code, event.target.checked);
3901
+ });
3902
+ }
3903
+ }), t(TRIGGER_CODE_LABELS[code])]
3904
+ }, code)),
3905
+ unknownCodes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3906
+ className: FallbacksCard_module_css_default.hint,
3907
+ children: t("triggerCodes.extra", { codes: unknownCodes.join(", ") })
3852
3908
  })
3853
3909
  ]
3854
3910
  }),
3855
3911
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3856
3912
  className: FallbacksCard_module_css_default.field,
3913
+ role: "group",
3914
+ "aria-labelledby": "fallbacks-revert-policy",
3857
3915
  children: [
3858
3916
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3859
3917
  className: FallbacksCard_module_css_default.fieldLabel,
3860
- children: [
3861
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3862
- htmlFor: "fallbacks-max-switches",
3863
- children: t("maxSwitchesPerStep.label")
3864
- }),
3865
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3866
- label: t("maxSwitchesPerStep.tooltip"),
3867
- disabled: !writable
3868
- }),
3869
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3870
- className: FallbacksCard_module_css_default.defaultNote,
3871
- children: [
3872
- t("defaults.prefix"),
3873
- ": ",
3874
- state.config.maxSwitchesPerStep
3875
- ]
3876
- })
3877
- ]
3878
- }),
3879
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3880
- id: "fallbacks-max-switches",
3881
- className: FallbacksCard_module_css_default.input,
3882
- type: "number",
3883
- min: 0,
3884
- value: String(scalars.maxSwitchesPerStep),
3885
- disabled: !writable,
3886
- onChange: (event) => {
3887
- updateScalars((draft) => {
3888
- draft.maxSwitchesPerStep = parseCount(event.target.value);
3889
- });
3890
- }
3918
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3919
+ id: "fallbacks-revert-policy",
3920
+ children: t("revertPolicy.label")
3921
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3922
+ label: t("revertPolicy.tooltip"),
3923
+ disabled: !writable
3924
+ })]
3891
3925
  }),
3892
3926
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3893
3927
  className: FallbacksCard_module_css_default.hint,
3894
- children: t("maxSwitchesPerStep.hint")
3895
- })
3928
+ children: t("revertPolicy.hint")
3929
+ }),
3930
+ ["cooldown-expiry", "never"].map((policy) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3931
+ className: FallbacksCard_module_css_default.optionRow,
3932
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3933
+ type: "radio",
3934
+ name: "fallbacks-revert-policy",
3935
+ checked: scalars.revertPolicy === policy,
3936
+ onChange: () => {
3937
+ updateScalars((draft) => {
3938
+ draft.revertPolicy = policy;
3939
+ });
3940
+ }
3941
+ }), t(`revertPolicy.${policy}`)]
3942
+ }, policy))
3896
3943
  ]
3897
3944
  }),
3898
3945
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3899
- className: FallbacksCard_module_css_default.field,
3946
+ className: FallbacksCard_module_css_default.numberFields,
3900
3947
  children: [
3901
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3902
- className: FallbacksCard_module_css_default.fieldLabel,
3948
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3949
+ className: FallbacksCard_module_css_default.field,
3903
3950
  children: [
3904
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3905
- htmlFor: "fallbacks-always-cap",
3906
- children: t("alwaysModeRetryCap.label")
3951
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3952
+ className: FallbacksCard_module_css_default.fieldLabel,
3953
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3954
+ htmlFor: "fallbacks-cooldown-ms",
3955
+ children: t("cooldownMs.label")
3956
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3957
+ label: cooldownMsTip,
3958
+ disabled: !writable
3959
+ })]
3907
3960
  }),
3908
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3909
- label: t("alwaysModeRetryCap.tooltip"),
3910
- disabled: !writable
3961
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3962
+ id: "fallbacks-cooldown-ms",
3963
+ className: FallbacksCard_module_css_default.input,
3964
+ type: "number",
3965
+ min: 0,
3966
+ value: String(scalars.cooldownMs),
3967
+ disabled: !writable,
3968
+ onChange: (event) => {
3969
+ updateScalars((draft) => {
3970
+ draft.cooldownMs = parseCount(event.target.value);
3971
+ });
3972
+ }
3911
3973
  }),
3912
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3913
- className: FallbacksCard_module_css_default.defaultNote,
3914
- children: [
3915
- t("defaults.prefix"),
3916
- ": ",
3917
- state.config.alwaysModeRetryCap
3918
- ]
3974
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3975
+ className: FallbacksCard_module_css_default.hint,
3976
+ children: t("cooldownMs.hint")
3919
3977
  })
3920
3978
  ]
3921
3979
  }),
3922
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3923
- id: "fallbacks-always-cap",
3924
- className: FallbacksCard_module_css_default.input,
3925
- type: "number",
3926
- min: 0,
3927
- value: String(scalars.alwaysModeRetryCap),
3928
- disabled: !writable,
3929
- onChange: (event) => {
3930
- updateScalars((draft) => {
3931
- draft.alwaysModeRetryCap = parseCount(event.target.value);
3932
- });
3933
- }
3980
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3981
+ className: FallbacksCard_module_css_default.field,
3982
+ children: [
3983
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3984
+ className: FallbacksCard_module_css_default.fieldLabel,
3985
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
3986
+ htmlFor: "fallbacks-max-switches",
3987
+ children: t("maxSwitchesPerStep.label")
3988
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
3989
+ label: maxSwitchesPerStepTip,
3990
+ disabled: !writable
3991
+ })]
3992
+ }),
3993
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3994
+ id: "fallbacks-max-switches",
3995
+ className: FallbacksCard_module_css_default.input,
3996
+ type: "number",
3997
+ min: 0,
3998
+ value: String(scalars.maxSwitchesPerStep),
3999
+ disabled: !writable,
4000
+ onChange: (event) => {
4001
+ updateScalars((draft) => {
4002
+ draft.maxSwitchesPerStep = parseCount(event.target.value);
4003
+ });
4004
+ }
4005
+ }),
4006
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4007
+ className: FallbacksCard_module_css_default.hint,
4008
+ children: t("maxSwitchesPerStep.hint")
4009
+ })
4010
+ ]
3934
4011
  }),
3935
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3936
- className: FallbacksCard_module_css_default.hint,
3937
- children: t("alwaysModeRetryCap.hint")
4012
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4013
+ className: FallbacksCard_module_css_default.field,
4014
+ children: [
4015
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4016
+ className: FallbacksCard_module_css_default.fieldLabel,
4017
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4018
+ htmlFor: "fallbacks-always-cap",
4019
+ children: t("alwaysModeRetryCap.label")
4020
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoHint, {
4021
+ label: alwaysModeRetryCapTip,
4022
+ disabled: !writable
4023
+ })]
4024
+ }),
4025
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4026
+ id: "fallbacks-always-cap",
4027
+ className: FallbacksCard_module_css_default.input,
4028
+ type: "number",
4029
+ min: 0,
4030
+ value: String(scalars.alwaysModeRetryCap),
4031
+ disabled: !writable,
4032
+ onChange: (event) => {
4033
+ updateScalars((draft) => {
4034
+ draft.alwaysModeRetryCap = parseCount(event.target.value);
4035
+ });
4036
+ }
4037
+ }),
4038
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4039
+ className: FallbacksCard_module_css_default.hint,
4040
+ children: t("alwaysModeRetryCap.hint")
4041
+ })
4042
+ ]
3938
4043
  })
3939
4044
  ]
4045
+ }),
4046
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4047
+ className: FallbacksCard_module_css_default.sectionActions,
4048
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4049
+ type: "button",
4050
+ className: FallbacksCard_module_css_default.discard,
4051
+ disabled: !advancedDirty || saving,
4052
+ onClick: () => {
4053
+ discardSection("advanced");
4054
+ },
4055
+ children: t("discard")
4056
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4057
+ type: "button",
4058
+ className: FallbacksCard_module_css_default.save,
4059
+ disabled: !writable || saving || !advancedDirty,
4060
+ onClick: () => {
4061
+ saveSection("advanced");
4062
+ },
4063
+ children: saving ? t("save.saving") : t("save")
4064
+ })]
3940
4065
  })
3941
4066
  ]
3942
4067
  })
3943
4068
  ]
3944
4069
  }),
3945
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3946
- className: FallbacksCard_module_css_default.footer,
3947
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3948
- type: "button",
3949
- className: FallbacksCard_module_css_default.discard,
3950
- disabled: !dirty || saving,
3951
- onClick: discard,
3952
- children: t("discard")
3953
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3954
- type: "button",
3955
- className: FallbacksCard_module_css_default.save,
3956
- disabled: !dirty || invalid || saving || !writable,
3957
- onClick: save,
3958
- children: saving ? t("save.saving") : t("save")
3959
- })]
3960
- }),
3961
4070
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3962
4071
  className: FallbacksCard_module_css_default.statusBlock,
3963
4072
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -4349,7 +4458,7 @@ window.__ModuleLoader__.load({
4349
4458
  * (`setCurrentSession` never called, `loadSwitches` ready with an empty
4350
4459
  * array, which the store already supports).
4351
4460
  *
4352
- * rc.1 dotted-namespace contract: each client Remote namespace is a
4461
+ * The host's dotted-namespace contract: each client Remote namespace is a
4353
4462
  * child-fiber service named `remote.<ns>` (upstream `remoteServiceKey`), and
4354
4463
  * the traceable proxy forwards `ctx.remote.llm` / `.settings` / `.session`
4355
4464
  * to those context properties — consumers MUST declare the dotted names
@@ -4368,7 +4477,7 @@ window.__ModuleLoader__.load({
4368
4477
  ];
4369
4478
  /**
4370
4479
  * The session the client is LOOKING at, derived from the sessions-list
4371
- * snapshot. 0.1.7-rc.1 moved view ownership out of `SessionListState` (the
4480
+ * snapshot. The host moved view ownership out of `SessionListState` (the
4372
4481
  * `current` field is gone — "navigation belongs to view owners"): the viewed
4373
4482
  * session is the one the shell retains under the `mainView` reference source,
4374
4483
  * surfaced as a positive `retainedBy.mainView` count on the row