dsh-llm-fallbacks 0.3.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,7 @@ window.__ModuleLoader__.load({
9
9
  //#endregion
10
10
  let react = require("react");
11
11
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
12
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
12
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
13
13
  let react_jsx_runtime = require("react/jsx-runtime");
14
14
  //#region node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js
15
15
  /**
@@ -538,6 +538,56 @@ window.__ModuleLoader__.load({
538
538
  return typeof entry.id === "string" && typeof entry.overridden === "boolean";
539
539
  });
540
540
  }
541
+ function parsePolicyRoute(value) {
542
+ if (!isRecord(value)) return void 0;
543
+ if (typeof value.provider !== "string" || value.provider.length === 0) return void 0;
544
+ if (typeof value.model !== "string" || value.model.length === 0) return void 0;
545
+ return {
546
+ provider: value.provider,
547
+ model: value.model
548
+ };
549
+ }
550
+ /**
551
+ * Shape-guard the additive `subagentPolicy` wire field (T5). Malformed
552
+ * payloads resolve to `undefined` (hide the status area) — the store never
553
+ * throws on an old or misshapen field (old-payload tolerance).
554
+ */
555
+ function parseSubagentPolicyWire(value) {
556
+ if (!isRecord(value) || typeof value.state !== "string") return void 0;
557
+ if (value.state === "disabled" || value.state === "unprovable") return { state: value.state };
558
+ if (value.state !== "enabled") return void 0;
559
+ if (!Array.isArray(value.allowedModels)) return void 0;
560
+ const allowedModels = [];
561
+ for (const entry of value.allowedModels) {
562
+ const route = parsePolicyRoute(entry);
563
+ if (route === void 0) return void 0;
564
+ allowedModels.push(route);
565
+ }
566
+ const view = {
567
+ state: "enabled",
568
+ allowedModels
569
+ };
570
+ if (isRecord(value.head) && (value.head.source === "authorized" || value.head.source === "injected")) {
571
+ const route = parsePolicyRoute(value.head.route);
572
+ if (route !== void 0) view.head = {
573
+ route,
574
+ source: value.head.source
575
+ };
576
+ }
577
+ if (isRecord(value.blockedAttempt) && typeof value.blockedAttempt.at === "number") {
578
+ const route = parsePolicyRoute(value.blockedAttempt.route);
579
+ if (route !== void 0) view.blockedAttempt = {
580
+ at: value.blockedAttempt.at,
581
+ route,
582
+ reason: typeof value.blockedAttempt.reason === "string" ? value.blockedAttempt.reason : ""
583
+ };
584
+ }
585
+ return view;
586
+ }
587
+ function subagentPolicyFromWire(value, fallback) {
588
+ if (!isRecord(value) || !("subagentPolicy" in value)) return fallback;
589
+ return parseSubagentPolicyWire(value.subagentPolicy);
590
+ }
541
591
  /** Seed-default persona from a revert-seed wire body (issue #59). */
542
592
  function revertOutcomePersona(value) {
543
593
  if (value === null || typeof value !== "object" || !("outcome" in value)) return void 0;
@@ -702,13 +752,14 @@ window.__ModuleLoader__.load({
702
752
  }
703
753
  /**
704
754
  * Extract the most recent `fallbacks/switch` events from one history page
705
- * (spec §2.5 D-5): filter by event type, order by `seq` descending, take at
706
- * most `limit`. Single-page read — fewer than `limit` events show as-is; no
707
- * multi-page backfill (Non-Goal).
755
+ * (spec §2.5 D-5): drop packed chunk runs, filter by event type, order by
756
+ * `seq` descending, take at most `limit`. Single-page read — fewer than
757
+ * `limit` events show as-is; no multi-page backfill (Non-Goal).
708
758
  */
709
759
  function extractRecentSwitches(entries, limit = 5) {
710
760
  const switches = [];
711
761
  for (const entry of entries) {
762
+ if (entry.type !== "event") continue;
712
763
  const event = entry.event;
713
764
  if (event.type !== "fallbacks/switch") continue;
714
765
  switches.push({
@@ -878,7 +929,7 @@ window.__ModuleLoader__.load({
878
929
  api;
879
930
  rpc;
880
931
  /** Snapshot consumed by the section through `useSyncExternalStore`. */
881
- store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
932
+ store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
882
933
  status: "idle",
883
934
  error: null,
884
935
  writable: false,
@@ -894,7 +945,8 @@ window.__ModuleLoader__.load({
894
945
  catalogEpoch: 0,
895
946
  switchesStatus: "idle",
896
947
  switchesError: null,
897
- switches: []
948
+ switches: [],
949
+ subagentPolicy: void 0
898
950
  });
899
951
  /** Read guard: a newer load() supersedes an older one's publish. */
900
952
  readGeneration = 0;
@@ -910,8 +962,18 @@ window.__ModuleLoader__.load({
910
962
  namespaces = /* @__PURE__ */ new Map();
911
963
  currentSession;
912
964
  /**
913
- * @param api - Settings / Llm / Sessions wire faces (describe `writable` +
914
- * namespace directory, provider/model catalog, session history).
965
+ * The store's dispose signal (qc3 F-003): created alongside the store
966
+ * lifecycle, threaded into every `session.follow` call, aborted once in
967
+ * {@link dispose} — a follow opening still mid-await at plugin unload
968
+ * (HMR / fiber dispose, or a wedged gateway stream) is cancelled promptly
969
+ * instead of staying open until the mount abort or socket failure.
970
+ */
971
+ followAbort = new AbortController();
972
+ /**
973
+ * @param api - the Remote namespace faces the store reads (settings
974
+ * describe `writable` + namespace directory, llm provider directory,
975
+ * session model catalog + follow tail page) — `ctx.remote` cast once at
976
+ * the mount boundary.
915
977
  * @param rpc - the connection's generic RPC caller for the host gateway
916
978
  * channel (`/api`), injected from the connection handle.
917
979
  */
@@ -941,12 +1003,12 @@ window.__ModuleLoader__.load({
941
1003
  state.error = null;
942
1004
  });
943
1005
  try {
944
- const [describeResult, getResult] = await Promise.all([this.api.settings.describe({}), this.rpc.call("/api", "fallbacks/get", { args: {} }).catch(() => void 0)]);
1006
+ const [describeResult, getResult] = await Promise.all([this.api.settings.describe(), this.rpc.call("/api", "fallbacks/get", { args: {} }).catch(() => void 0)]);
945
1007
  if (generation !== this.readGeneration) return;
946
1008
  if (writeGenerationAtStart !== this.writeGeneration) return;
947
- if (!describeResult.result.ok) throw describeResult.result.error;
948
- this.namespaces = new Map(describeResult.result.value.namespaces.map((entry) => [entry.ns, entry]));
949
- const writable = describeResult.result.value.writable;
1009
+ if (!describeResult.ok) throw describeResult.error;
1010
+ this.namespaces = new Map(describeResult.value.namespaces.map((entry) => [entry.ns, entry]));
1011
+ const writable = describeResult.value.writable;
950
1012
  let config;
951
1013
  let legacyKeys = [];
952
1014
  let seeds = [];
@@ -958,7 +1020,8 @@ window.__ModuleLoader__.load({
958
1020
  }
959
1021
  if ("seeds" in getResult.value) seeds = parseSeedsWire(getResult.value.seeds);
960
1022
  }
961
- this.accept(config, writable, legacyKeys, seeds);
1023
+ const subagentPolicy = getResult !== void 0 && getResult.ok ? subagentPolicyFromWire(getResult.value, void 0) : void 0;
1024
+ this.accept(config, writable, legacyKeys, seeds, subagentPolicy);
962
1025
  } catch (error) {
963
1026
  if (generation !== this.readGeneration) return;
964
1027
  if (writeGenerationAtStart !== this.writeGeneration) return;
@@ -966,7 +1029,8 @@ window.__ModuleLoader__.load({
966
1029
  }
967
1030
  }
968
1031
  /**
969
- * Refresh the provider/model catalog (`llm.providers` + `llm.models`), an
1032
+ * Refresh the provider/model catalog (`llm/listConfigurableProviders` +
1033
+ * `session/modelCatalog`), an
970
1034
  * independent read path with its own generation guard so it can run
971
1035
  * parallel to {@link load} without clobbering it (spec §2.5 D-4).
972
1036
  * Per-provider lookup failures ride `catalogError` as a diagnostic without
@@ -981,13 +1045,13 @@ window.__ModuleLoader__.load({
981
1045
  state.catalogError = null;
982
1046
  });
983
1047
  try {
984
- const [providersResponse, modelsResponse] = await Promise.all([this.api.llm.providers({}), this.api.llm.models({})]);
1048
+ const [providersResponse, catalogResponse] = await Promise.all([this.api.llm.listConfigurableProviders(), this.api.session.modelCatalog()]);
985
1049
  if (generation !== this.catalogGeneration) return;
986
- if (!providersResponse.result.ok) throw providersResponse.result.error;
987
- if (!modelsResponse.result.ok) throw modelsResponse.result.error;
988
- const providers = providersResponse.result.value.providers;
989
- const groups = modelsResponse.result.value.groups;
990
- const failures = modelsResponse.result.value.failures;
1050
+ if (!providersResponse.ok) throw providersResponse.error;
1051
+ if (!catalogResponse.ok) throw catalogResponse.error;
1052
+ const providers = providersResponse.value;
1053
+ const groups = catalogResponse.value.groups;
1054
+ const failures = catalogResponse.value.failures;
991
1055
  this.store.update((state) => {
992
1056
  state.catalogStatus = "ready";
993
1057
  state.catalogError = failures.length > 0 ? failures.map((failure) => `${failure.name}: ${failure.message}`).join("; ") : null;
@@ -1020,7 +1084,10 @@ window.__ModuleLoader__.load({
1020
1084
  }
1021
1085
  /**
1022
1086
  * Read the recent-switch summary for the current session (spec §2.5 D-5):
1023
- * one `sessions.history` page (`maxMessages` = {@link SWITCHES_HISTORY_PAGE}),
1087
+ * one tail page (`maxMessages` = {@link SWITCHES_HISTORY_PAGE}) read from
1088
+ * the `session/follow` opening snapshot — 0.1.2 has no unary tail-page
1089
+ * read (`session/page` needs the follow opening frame's cursor), so the
1090
+ * stream is cancelled right after its first frame —
1024
1091
  * `fallbacks/switch` events extracted newest-first capped at
1025
1092
  * {@link RECENT_SWITCH_LIMIT}. No current session → honest empty ready
1026
1093
  * state (no RPC); a read failure lands `switchesStatus: 'error'` and never
@@ -1043,13 +1110,22 @@ window.__ModuleLoader__.load({
1043
1110
  state.switchesError = null;
1044
1111
  });
1045
1112
  try {
1046
- const response = await this.api.sessions.history({
1047
- sessionId,
1113
+ const iterator = this.api.session.follow({
1114
+ address: {
1115
+ kind: "session",
1116
+ sessionId
1117
+ },
1048
1118
  maxMessages: 50
1049
- });
1119
+ }, this.followAbort.signal)[Symbol.asyncIterator]();
1120
+ let first;
1121
+ try {
1122
+ first = await iterator.next();
1123
+ } finally {
1124
+ await iterator.return?.();
1125
+ }
1050
1126
  if (generation !== this.switchesGeneration) return;
1051
- if (!response.result.ok) throw response.result.error;
1052
- const switches = extractRecentSwitches(response.result.value.events);
1127
+ if (first.done || first.value.type !== "snapshot") throw new Error("session follow closed before its opening snapshot");
1128
+ const switches = extractRecentSwitches(first.value.records);
1053
1129
  this.store.update((state) => {
1054
1130
  state.switchesStatus = "ready";
1055
1131
  state.switchesError = null;
@@ -1099,7 +1175,8 @@ window.__ModuleLoader__.load({
1099
1175
  const wireSeeds = value.seeds;
1100
1176
  if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
1101
1177
  }
1102
- this.accept(config, true, legacyKeys, seeds);
1178
+ const subagentPolicy = subagentPolicyFromWire(value, this.store.getSnapshot().subagentPolicy);
1179
+ this.accept(config, true, legacyKeys, seeds, subagentPolicy);
1103
1180
  } catch (error) {
1104
1181
  if (generation !== this.writeGeneration) return;
1105
1182
  this.fail(error);
@@ -1135,7 +1212,8 @@ window.__ModuleLoader__.load({
1135
1212
  const wireSeeds = value.seeds;
1136
1213
  if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
1137
1214
  }
1138
- this.accept(config, true, legacyKeys, seeds);
1215
+ const subagentPolicy = subagentPolicyFromWire(value, this.store.getSnapshot().subagentPolicy);
1216
+ this.accept(config, true, legacyKeys, seeds, subagentPolicy);
1139
1217
  } catch (error) {
1140
1218
  if (generation !== this.writeGeneration) return;
1141
1219
  this.fail(error);
@@ -1183,7 +1261,8 @@ window.__ModuleLoader__.load({
1183
1261
  const wireSeeds = value.seeds;
1184
1262
  if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
1185
1263
  }
1186
- this.accept(config, true, legacyKeys, seeds);
1264
+ const subagentPolicy = subagentPolicyFromWire(value, this.store.getSnapshot().subagentPolicy);
1265
+ this.accept(config, true, legacyKeys, seeds, subagentPolicy);
1187
1266
  return revertOutcomePersona(value);
1188
1267
  } catch (error) {
1189
1268
  if (generation !== this.writeGeneration) return void 0;
@@ -1198,6 +1277,7 @@ window.__ModuleLoader__.load({
1198
1277
  this.catalogGeneration += 1;
1199
1278
  this.switchesGeneration += 1;
1200
1279
  this.namespaces = /* @__PURE__ */ new Map();
1280
+ this.followAbort.abort();
1201
1281
  }
1202
1282
  /**
1203
1283
  * Publish a settled load: `status` ready, `writable` from describe, and —
@@ -1215,7 +1295,7 @@ window.__ModuleLoader__.load({
1215
1295
  * only when a real config resolved — a transient channel-down keeps the
1216
1296
  * last accepted badge state.
1217
1297
  */
1218
- accept(config, writable, legacyKeys, seeds) {
1298
+ accept(config, writable, legacyKeys, seeds, subagentPolicy) {
1219
1299
  const parsed = config === void 0 ? void 0 : parseFallbacksConfig(config);
1220
1300
  this.store.update((state) => {
1221
1301
  state.status = "ready";
@@ -1224,6 +1304,7 @@ window.__ModuleLoader__.load({
1224
1304
  state.present = parsed !== void 0;
1225
1305
  state.legacyKeys = parsed === void 0 ? state.legacyKeys : legacyKeys;
1226
1306
  state.seeds = parsed === void 0 ? state.seeds : seeds;
1307
+ state.subagentPolicy = parsed === void 0 ? state.subagentPolicy : subagentPolicy;
1227
1308
  if (parsed !== void 0) state.config = parsed;
1228
1309
  state.configuredProviders = configuredProvidersOf(state.providers, this.namespaces);
1229
1310
  });
@@ -1327,6 +1408,13 @@ window.__ModuleLoader__.load({
1327
1408
  "chains.selector.noModelsStrict": "该 provider 暂无可用模型(目录查询失败),请改选其他 provider。",
1328
1409
  "mainAgent.label": "主代理",
1329
1410
  "subagents.label": "子代理",
1411
+ "subagents.policy.label": "宿主子代理模型策略",
1412
+ "subagents.policy.allowlist": "允许的模型",
1413
+ "subagents.policy.head": "当前链头",
1414
+ "subagents.policy.source.authorized": "宿主授权",
1415
+ "subagents.policy.source.injected": "插件注入",
1416
+ "subagents.policy.blocked": "降级候选均不在允许列表中 — 未切换",
1417
+ "subagents.policy.unprovable": "策略存在但无法读取 — 插件切换已禁用",
1330
1418
  "timeSlots.label": "分时槽设置",
1331
1419
  "timeSlots.hint": "自上而下第一条命中生效;全时段行固定最后",
1332
1420
  "timeSlots.tz.label": "时区(UTC±)",
@@ -1512,6 +1600,13 @@ window.__ModuleLoader__.load({
1512
1600
  "chains.selector.noModelsStrict": "No models available for this provider (catalog lookup failed); pick another provider.",
1513
1601
  "mainAgent.label": "Main agent",
1514
1602
  "subagents.label": "Subagents",
1603
+ "subagents.policy.label": "Host subagent model policy",
1604
+ "subagents.policy.allowlist": "Allowed models",
1605
+ "subagents.policy.head": "Effective chain head",
1606
+ "subagents.policy.source.authorized": "authorized",
1607
+ "subagents.policy.source.injected": "injected",
1608
+ "subagents.policy.blocked": "No in-allowlist fallback candidate — switch skipped",
1609
+ "subagents.policy.unprovable": "Policy present but unreadable — plugin switches disabled",
1515
1610
  "timeSlots.label": "Time slots",
1516
1611
  "timeSlots.hint": "First match from top to bottom wins; the all-day row is always last",
1517
1612
  "timeSlots.tz.label": "Timezone (UTC±)",
@@ -1684,7 +1779,7 @@ window.__ModuleLoader__.load({
1684
1779
  }
1685
1780
  //#endregion
1686
1781
  //#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/FallbacksCard.module.css.mjs
1687
- const css$2 = "\n\n\n._8827595f_card {\n list-style: none;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n\n._8827595f_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._06704203_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._e488d460_header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n\n._e488d460_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n\n._f5dfe084_headText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n._8d39bde6_name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n\n._346f3b69_description {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._631094a0_chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n\n._44836ce8_chevronOpen {\n transform: rotate(180deg);\n}\n\n\n._dbaa7975_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding-bottom: 8px;\n}\n\n._4e39cf17_readOnly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._99bf7f3c_pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n\n\n\n\n._9860a5b1_notice {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n\n._5006d43e_legacyNotice {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n._21918751_error {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._7cea4b2f_noticeRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 12px 0 0;\n}\n\n._7cea4b2f_noticeRow ._21918751_error {\n flex: 1;\n min-width: 0;\n margin: 0;\n}\n\n\n._4058c747_form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 0 0;\n}\n\n\n._9998065c_checkboxRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._02c2f6df_checkLabel {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 14px;\n line-height: 22px;\n font-weight: 400;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._f2d47237_checkLabelTitle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-weight: 400;\n}\n\n._c1bed8ea_checkLabelDesc {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._06389b18_checkbox {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._94c91bfd_fieldset {\n margin: 0;\n padding: 0;\n border: none;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n\n._67826267_field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n}\n\n._13e68c3f_fieldLabel {\n \n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._ba240d82_sectionHeading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n._ddbc1b49_sectionHeadingText {\n flex: 1;\n min-width: 0;\n}\n\n\n._c41f9db7_sectionActions {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n}\n\n\n._b116c758_sectionToggle {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n._b116c758_sectionToggle:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n\n._b116c758_sectionToggle:disabled {\n cursor: default;\n}\n\n._b116c758_sectionToggle:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 6px;\n}\n\n._a5313fdf_sectionToggleText {\n flex: 1;\n min-width: 0;\n text-align: left;\n}\n\n._4bc809b8_hint {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._579f813a_defaultNote {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._b1962759_slotPresetName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._a6244318_infoHint {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n font-size: 14px;\n line-height: 1;\n color: var(--dsw-alias-label-tertiary);\n background: var(--dsw-alias-interactive-bg-hover);\n cursor: help;\n user-select: none;\n}\n\n._a6244318_infoHint:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._e655c840_infoHintDisabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._a2521bb0_optionRow {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._a2521bb0_optionRow:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n\n._06389b18_checkbox,\n._a2521bb0_optionRow input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:focus-visible,\n._a2521bb0_optionRow input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._a2521bb0_optionRow input:disabled {\n cursor: default;\n}\n\n\n._c4ecbdf3_dayRow {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n._0330c1ed_dayCell {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n border-radius: 6px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n._0330c1ed_dayCell input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell input:disabled {\n cursor: default;\n}\n\n._0330c1ed_dayCell input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._f9d86f7b_input {\n box-sizing: border-box;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n}\n\n._f9d86f7b_input:focus {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n\n._f9d86f7b_input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n._f9d86f7b_input:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n\n._3a9b42fd_inputTextarea {\n height: auto;\n min-height: 72px;\n padding: 6px 10px;\n resize: vertical;\n line-height: 20px;\n}\n\n\n._7b60337a_inputInvalid,\n._7b60337a_inputInvalid:focus {\n border-color: var(--dsw-alias-state-error-primary);\n}\n\n\nselect._f9d86f7b_input {\n max-width: 240px;\n cursor: pointer;\n}\n\n\n._16eb7153_selectInput {\n appearance: none;\n padding-right: 32px;\n \n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n background-size: 12px 12px;\n}\n\n\n._3e95886d_numberFields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n}\n\n._0cfb5881_list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n\n._f5c620d6_editorCard {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n}\n\n._224b1387_cardFoot {\n display: flex;\n justify-content: flex-end;\n}\n\n._8e220e07_ruleGrid {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n._24a12a2f_ruleCell {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 120px;\n flex: 1;\n}\n\n\n._86bc52d2_collapseRow {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n._a73efcc6_collapseToggle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n font: inherit;\n text-align: left;\n}\n\n._a73efcc6_collapseToggle:disabled {\n cursor: default;\n}\n\n._af017718_collapseTitle {\n \n flex: none;\n max-width: 55%;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n._2cabe603_collapseMeta {\n \n flex: none;\n margin-left: auto;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n._7b04f727_slotTag {\n flex: none;\n display: inline-flex;\n align-items: center;\n border-radius: 999px;\n padding: 0 6px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n border: 1px solid;\n}\n\n._c381e792_slotTagHighCost {\n color: var(--dsw-alias-state-error-primary);\n border-color: var(--dsw-alias-state-error-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n._23bdb6fc_slotTagMultiplier {\n color: var(--dsw-alias-state-warn-primary);\n border-color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 10%, transparent);\n}\n\n._f000eed9_slotTagActive {\n color: var(--dsw-alias-state-success-primary);\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent);\n}\n\n\n._cd905ce5_dragHandle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: grab;\n color: var(--dsw-alias-label-tertiary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 6px;\n flex: none;\n}\n\n._cd905ce5_dragHandle:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._cd905ce5_dragHandle:active {\n cursor: grabbing;\n}\n\n._cd905ce5_dragHandle:disabled {\n cursor: default;\n opacity: 0.4;\n}\n\n._cd905ce5_dragHandle:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._49f0c4f0_dragHandleIcon {\n transform: rotate(90deg);\n}\n\n\n._fee63b7e_slotCardDragging {\n opacity: 0.45;\n}\n\n._6f108491_slotCardOver {\n outline: 1px dashed var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n._1014c097_ruleCellLabel {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._15a12620_chainSelectors {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n._240cbbf8_selectorRow {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n\n._70effa64_iconButton {\n position: relative;\n box-sizing: border-box;\n appearance: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 6px;\n background: none;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n._70effa64_iconButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._70effa64_iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._70effa64_iconButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._70effa64_iconButton::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%);\n padding: 3px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n font-size: 11px;\n line-height: 17px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity .12s;\n}\n\n._70effa64_iconButton:hover::after,\n._70effa64_iconButton:focus-visible::after {\n opacity: 1;\n}\n\n\n._a0968257_iconButtonDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._28202c90_addButton {\n align-self: flex-start;\n}\n\n\n._6a2bd54c_slotAddRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n flex-wrap: wrap;\n}\n\n\n._4e77523e_rowActions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n\n._747fd56d_primaryButton,\n._7e855445_secondaryButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n._747fd56d_primaryButton {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n._747fd56d_primaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n._7e855445_secondaryButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n\n._7e855445_secondaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n\n._747fd56d_primaryButton:disabled,\n._7e855445_secondaryButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._747fd56d_primaryButton:focus-visible,\n._7e855445_secondaryButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._238d19be_sectionAction {\n height: 28px;\n padding: 0 12px;\n border-radius: 14px;\n font-size: 12px;\n line-height: 18px;\n}\n\n\n._fbd045e0_statusBlock {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 14px;\n margin-top: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n}\n\n._d4f70367_statusTitle {\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._8ab300ed_statusLine {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._e8cedbf5_statusLineLabel {\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._b48dfcba_offNotice {\n margin: 0;\n padding: 12px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 8px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._70effa64_iconButton::after {\n transition: none;\n }\n}\n";
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";
1688
1783
  const tagId$2 = "dsh-llm-fallbacks/FallbacksCard.module.css";
1689
1784
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
1690
1785
  const tag = document.createElement("style");
@@ -1768,7 +1863,11 @@ window.__ModuleLoader__.load({
1768
1863
  "statusTitle": "_d4f70367_statusTitle",
1769
1864
  "statusLine": "_8ab300ed_statusLine",
1770
1865
  "statusLineLabel": "_e8cedbf5_statusLineLabel",
1771
- "offNotice": "_b48dfcba_offNotice"
1866
+ "offNotice": "_b48dfcba_offNotice",
1867
+ "policyStatus": "_700006c9_policyStatus",
1868
+ "policyStatusLabel": "_d4b67a81_policyStatusLabel",
1869
+ "policyStatusLine": "_278bb4b3_policyStatusLine",
1870
+ "policyStatusWarn": "_da6387e5_policyStatusWarn"
1772
1871
  };
1773
1872
  //#endregion
1774
1873
  //#region src/client/FallbacksCard.tsx
@@ -3382,6 +3481,38 @@ window.__ModuleLoader__.load({
3382
3481
  role: "alert",
3383
3482
  children: t("error.generic", { message: state.error })
3384
3483
  }),
3484
+ state.subagentPolicy?.state === "enabled" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3485
+ className: FallbacksCard_module_css_default.policyStatus,
3486
+ role: "status",
3487
+ children: [
3488
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3489
+ className: FallbacksCard_module_css_default.policyStatusLabel,
3490
+ children: t("subagents.policy.label")
3491
+ }),
3492
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3493
+ className: FallbacksCard_module_css_default.policyStatusLine,
3494
+ children: `${t("subagents.policy.allowlist")}: ${state.subagentPolicy.allowedModels.map((route) => `${route.provider}/${route.model}`).join(", ")}`
3495
+ }),
3496
+ state.subagentPolicy.head !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3497
+ className: FallbacksCard_module_css_default.policyStatusLine,
3498
+ children: `${t("subagents.policy.head")}: ${state.subagentPolicy.head.route.provider}/${state.subagentPolicy.head.route.model} (${t(state.subagentPolicy.head.source === "authorized" ? "subagents.policy.source.authorized" : "subagents.policy.source.injected")})`
3499
+ }),
3500
+ state.subagentPolicy.blockedAttempt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3501
+ className: FallbacksCard_module_css_default.policyStatusWarn,
3502
+ role: "alert",
3503
+ children: t("subagents.policy.blocked")
3504
+ })
3505
+ ]
3506
+ }),
3507
+ state.subagentPolicy?.state === "unprovable" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3508
+ className: FallbacksCard_module_css_default.policyStatus,
3509
+ role: "status",
3510
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3511
+ className: FallbacksCard_module_css_default.policyStatusWarn,
3512
+ role: "alert",
3513
+ children: t("subagents.policy.unprovable")
3514
+ })
3515
+ }),
3385
3516
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3386
3517
  className: FallbacksCard_module_css_default.field,
3387
3518
  role: "group",
@@ -4347,12 +4478,12 @@ window.__ModuleLoader__.load({
4347
4478
  //#region src/client/index.ts
4348
4479
  /**
4349
4480
  * Required services (cordis fiber inject); registrations wait on the slot
4350
- * declaration. `conversationEvents` is declared because the D1 Definition
4351
- * registration reads the service directly (`ctx.conversationEvents.register`
4481
+ * declaration. `uiConversation` is declared because the D1 Definition
4482
+ * registration reads the service directly (`ctx.uiConversation.events.register`
4352
4483
  * at the bottom of `apply` — explicit fiber-ordering parity with the
4353
4484
  * ui-workflow-run precedent, whose inject list includes it for the same
4354
- * direct read). The runtime would still provide the service synchronously
4355
- * on apply, but the declaration makes the dependency honest. `sessions` is
4485
+ * direct read). Cordis would still provide the service synchronously on
4486
+ * apply, but the declaration makes the dependency honest. `sessions` is
4356
4487
  * deliberately NOT injected (S-g): a non-web host without the dsh-session
4357
4488
  * client service must not hang the fiber waiting for it — the wiring reads
4358
4489
  * it reflectively and degrades to the switches empty state when absent
@@ -4364,7 +4495,7 @@ window.__ModuleLoader__.load({
4364
4495
  "locale",
4365
4496
  "connection",
4366
4497
  "remote",
4367
- "conversationEvents"
4498
+ "uiConversation"
4368
4499
  ];
4369
4500
  /**
4370
4501
  * Register the `fallbacks` dictionaries and the plugin-config card once the
@@ -4378,7 +4509,7 @@ window.__ModuleLoader__.load({
4378
4509
  }), "llm-fallbacks: dictionaries");
4379
4510
  const connection = ctx.get("connection");
4380
4511
  const sessions = ctx.get("sessions");
4381
- const controller = new FallbacksSettingsController(connection.api, connection.rpc);
4512
+ const controller = new FallbacksSettingsController(ctx.remote, connection.rpc);
4382
4513
  const useSnapshot = bindSnapshotSelector(controller.store);
4383
4514
  ctx.effect(() => {
4384
4515
  const syncSession = () => {
@@ -4442,7 +4573,7 @@ window.__ModuleLoader__.load({
4442
4573
  })
4443
4574
  }, GeneralFallbacksRow);
4444
4575
  });
4445
- ctx.effect(() => ctx.conversationEvents.register(fallbackSwitchDefinition), "llm-fallbacks: conversation node definition");
4576
+ ctx.effect(() => ctx.uiConversation.events.register(fallbackSwitchDefinition), "llm-fallbacks: conversation node definition");
4446
4577
  ctx.slots.inject("conversation.chat.node", function* () {
4447
4578
  yield ctx.slots.register({
4448
4579
  name: "conversation.chat.node",
@@ -50,6 +50,13 @@ export declare const zh: {
50
50
  'chains.selector.noModelsStrict': string;
51
51
  'mainAgent.label': string;
52
52
  'subagents.label': string;
53
+ 'subagents.policy.label': string;
54
+ 'subagents.policy.allowlist': string;
55
+ 'subagents.policy.head': string;
56
+ 'subagents.policy.source.authorized': string;
57
+ 'subagents.policy.source.injected': string;
58
+ 'subagents.policy.blocked': string;
59
+ 'subagents.policy.unprovable': string;
53
60
  'timeSlots.label': string;
54
61
  'timeSlots.hint': string;
55
62
  'timeSlots.tz.label': string;
@@ -237,6 +244,13 @@ export declare const en: {
237
244
  'chains.selector.noModelsStrict': string;
238
245
  'mainAgent.label': string;
239
246
  'subagents.label': string;
247
+ 'subagents.policy.label': string;
248
+ 'subagents.policy.allowlist': string;
249
+ 'subagents.policy.head': string;
250
+ 'subagents.policy.source.authorized': string;
251
+ 'subagents.policy.source.injected': string;
252
+ 'subagents.policy.blocked': string;
253
+ 'subagents.policy.unprovable': string;
240
254
  'timeSlots.label': string;
241
255
  'timeSlots.hint': string;
242
256
  'timeSlots.tz.label': string;
@@ -48,7 +48,7 @@ export interface FallbacksCommandAgent {
48
48
  readonly header?: {
49
49
  readonly origin?: Origin;
50
50
  };
51
- readonly events: readonly unknown[];
51
+ readonly snapshotEvents: () => readonly unknown[];
52
52
  };
53
53
  }
54
54
  /** One active cooldown entry displayed by `/fallbacks`. */
package/dist/gateway.d.ts CHANGED
@@ -59,12 +59,73 @@
59
59
  * @module dsh-llm-fallbacks/gateway
60
60
  */
61
61
  import type { Context } from '@deepseek-ai/cordis';
62
+ import type { SettingsNamespace } from '@deepseek-ai/dsh-settings';
62
63
  import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
63
64
  import type { TypertContribution } from '@deepseek-ai/dsh-typert-registry';
64
65
  import type { FallbacksConfig } from './config';
65
66
  import type { FallbacksSeedManager, SeedRevertOutcome, SeedsWireStatus } from './seeds';
66
- /** The `fallbacks` settings namespace (registered when a settings service exists). */
67
- export declare const FALLBACKS_SETTINGS_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace;
67
+ /**
68
+ * The `fallbacks` settings namespace (registered when a settings service
69
+ * exists). 0.1.2 removed the `settingsNamespace` helper: the registered
70
+ * namespace is the lowercase-hyphenated literal itself, branded through the
71
+ * `SettingsNamespace` type the service APIs constrain on.
72
+ */
73
+ export declare const FALLBACKS_SETTINGS_NAMESPACE: SettingsNamespace;
74
+ /** One exact child LLM route on the additive `subagentPolicy` wire field (T5). */
75
+ export type SubagentPolicyRoute = {
76
+ provider: string;
77
+ model: string;
78
+ };
79
+ /**
80
+ * Additive `/api/fallbacks/get` host-policy snapshot (spec D4 / T5).
81
+ * Omitted only when the snapshot is unwired (3-arg constructor) so older
82
+ * clients and gateway unit tests keep a byte-identical `{ config,
83
+ * legacyKeys, seeds }` payload. A wired snapshot always emits the field —
84
+ * `{ state: 'disabled' }` included — so a write after an enabled get cannot
85
+ * keep-last an allowlist. Never written through `set`/`reset`.
86
+ */
87
+ export type SubagentPolicyWire = {
88
+ state: 'enabled';
89
+ allowedModels: SubagentPolicyRoute[];
90
+ head?: {
91
+ route: SubagentPolicyRoute;
92
+ source: 'authorized' | 'injected';
93
+ };
94
+ blockedAttempt?: {
95
+ at: number;
96
+ route: SubagentPolicyRoute;
97
+ reason: string;
98
+ };
99
+ } | {
100
+ state: 'disabled';
101
+ } | {
102
+ state: 'unprovable';
103
+ };
104
+ /**
105
+ * Live host-policy snapshot the gateway projects onto the wire. Built in
106
+ * `apply()` from the SAME T1 reader the override paths use — no second
107
+ * policy source. Optional: the 3-arg constructor (gateway unit tests)
108
+ * omits the field entirely.
109
+ */
110
+ export type SubagentPolicySnapshotFn = () => {
111
+ policy: {
112
+ state: 'disabled';
113
+ } | {
114
+ state: 'enabled';
115
+ allowedModels: readonly SubagentPolicyRoute[];
116
+ } | {
117
+ state: 'unprovable';
118
+ };
119
+ head?: {
120
+ route: SubagentPolicyRoute;
121
+ source: 'authorized' | 'injected';
122
+ };
123
+ blockedAttempt?: {
124
+ at: number;
125
+ route: SubagentPolicyRoute;
126
+ reason: string;
127
+ };
128
+ };
68
129
  /**
69
130
  * The live configuration source for the gateway (guide §7 — the same bridge
70
131
  * shape the runtime reads through). `source()` returns the live composed
@@ -87,6 +148,13 @@ export interface FallbacksReadResult {
87
148
  config: FallbacksConfig;
88
149
  legacyKeys: string[];
89
150
  seeds: SeedsWireStatus[];
151
+ /**
152
+ * Host subagent-model-selection policy (spec D4). Additive — old readers
153
+ * ignore it; omitted only when no snapshot is wired. A wired snapshot
154
+ * always carries the field (`disabled` included) so keep-last cannot
155
+ * retain an allowlist after policy-off.
156
+ */
157
+ subagentPolicy?: SubagentPolicyWire;
90
158
  }
91
159
  /** The `fallbacks/revert-seed` response — a read result plus the revert outcome. */
92
160
  export interface FallbacksRevertResult extends FallbacksReadResult {
@@ -110,6 +178,12 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
110
178
  private readonly seeds;
111
179
  /** The live settings service once the optional inject child activates. */
112
180
  private settings;
181
+ /**
182
+ * Optional host-policy snapshot (T5). When omitted the additive
183
+ * `subagentPolicy` field is absent on every read — the 3-arg constructor
184
+ * used by gateway unit tests stays byte-identical to the pre-T5 payload.
185
+ */
186
+ private readonly subagentPolicy;
113
187
  /**
114
188
  * @param ctx - owning context (the plugin fiber's ctx inside `apply`).
115
189
  * @param bridge - the same `FallbacksSettingsBridge` the runtime reads, so
@@ -117,8 +191,10 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
117
191
  * @param seeds - the per-apply `FallbacksSeedManager` constructed in
118
192
  * `apply()` — the gateway delegates badge state and revert to it (no
119
193
  * copied manager logic), through the io seam built over this bridge.
194
+ * @param subagentPolicy - live host-policy snapshot from `apply()`; omit
195
+ * to leave the additive field off the wire.
120
196
  */
121
- constructor(ctx: Context, bridge: FallbacksSettingsBridge, seeds: FallbacksSeedManager);
197
+ constructor(ctx: Context, bridge: FallbacksSettingsBridge, seeds: FallbacksSeedManager, subagentPolicy?: SubagentPolicySnapshotFn);
122
198
  /**
123
199
  * Read the current composed config (schema defaults → entry base → settings
124
200
  * user layer). No hard-gate resolver (ADR-2): the raw composed config is