dsh-llm-fallbacks 0.3.4 → 0.4.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/README.zh-CN.md +26 -2
- package/dist/authorized-route.d.ts +68 -0
- package/dist/client/ConversationFallbackSwitch.d.ts +18 -14
- package/dist/client/fallbacks-store.d.ts +120 -18
- package/dist/client/index.d.ts +9 -8
- package/dist/client/index.js +176 -41
- package/dist/client/locales.d.ts +14 -0
- package/dist/commands.d.ts +4 -0
- package/dist/config.d.ts +14 -0
- package/dist/cooldown.d.ts +9 -0
- package/dist/gateway.d.ts +79 -3
- package/dist/index.d.ts +25 -5
- package/dist/index.js +470 -50
- package/dist/override.d.ts +39 -0
- package/dist/recovery.d.ts +92 -0
- package/dist/route-allowlist.d.ts +43 -0
- package/dist/state.d.ts +67 -2
- package/dist/subagent-policy.d.ts +123 -0
- package/dist/virtual-adapter.d.ts +49 -0
- package/package.json +25 -21
- package/scripts/build-client.ts +10 -6
package/dist/client/index.js
CHANGED
|
@@ -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
|
|
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
|
/**
|
|
@@ -486,7 +486,8 @@ window.__ModuleLoader__.load({
|
|
|
486
486
|
presets: "bundled",
|
|
487
487
|
roleAutoMatch: true,
|
|
488
488
|
timeSlots: [],
|
|
489
|
-
tz: "Asia/Shanghai"
|
|
489
|
+
tz: "Asia/Shanghai",
|
|
490
|
+
recovery: "timer"
|
|
490
491
|
};
|
|
491
492
|
/**
|
|
492
493
|
* Reserved role id: legal as a rule target (`roles.rules[].role`) and as
|
|
@@ -537,6 +538,56 @@ window.__ModuleLoader__.load({
|
|
|
537
538
|
return typeof entry.id === "string" && typeof entry.overridden === "boolean";
|
|
538
539
|
});
|
|
539
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
|
+
}
|
|
540
591
|
/** Seed-default persona from a revert-seed wire body (issue #59). */
|
|
541
592
|
function revertOutcomePersona(value) {
|
|
542
593
|
if (value === null || typeof value !== "object" || !("outcome" in value)) return void 0;
|
|
@@ -643,6 +694,8 @@ window.__ModuleLoader__.load({
|
|
|
643
694
|
}))) throw new TypeError("fallbacks descriptor timeSlots must be an array of slot rows (kind/preset/start/end strings, chain string array, days number array)");
|
|
644
695
|
const tz = value.tz;
|
|
645
696
|
if (tz !== void 0 && typeof tz !== "string") throw new TypeError("fallbacks descriptor tz must be a string");
|
|
697
|
+
const recovery = value.recovery;
|
|
698
|
+
if (recovery !== void 0 && recovery !== "timer" && recovery !== "half-open") throw new TypeError("fallbacks descriptor recovery must be timer|half-open");
|
|
646
699
|
return {
|
|
647
700
|
enabled: enabled ?? defaultFallbacksConfig.enabled,
|
|
648
701
|
triggerCodes: triggerCodes ?? [...defaultFallbacksConfig.triggerCodes],
|
|
@@ -658,7 +711,8 @@ window.__ModuleLoader__.load({
|
|
|
658
711
|
presets: presets ?? defaultFallbacksConfig.presets,
|
|
659
712
|
roleAutoMatch: roleAutoMatch ?? defaultFallbacksConfig.roleAutoMatch,
|
|
660
713
|
timeSlots: timeSlots ?? [...defaultFallbacksConfig.timeSlots ?? []],
|
|
661
|
-
tz: tz ?? defaultFallbacksConfig.tz
|
|
714
|
+
tz: tz ?? defaultFallbacksConfig.tz,
|
|
715
|
+
recovery: recovery ?? defaultFallbacksConfig.recovery
|
|
662
716
|
};
|
|
663
717
|
}
|
|
664
718
|
/** The raw selector string a selection serializes to ('' when empty). */
|
|
@@ -698,13 +752,14 @@ window.__ModuleLoader__.load({
|
|
|
698
752
|
}
|
|
699
753
|
/**
|
|
700
754
|
* Extract the most recent `fallbacks/switch` events from one history page
|
|
701
|
-
* (spec §2.5 D-5): filter by event type, order by
|
|
702
|
-
* most `limit`. Single-page read — fewer than
|
|
703
|
-
* 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).
|
|
704
758
|
*/
|
|
705
759
|
function extractRecentSwitches(entries, limit = 5) {
|
|
706
760
|
const switches = [];
|
|
707
761
|
for (const entry of entries) {
|
|
762
|
+
if (entry.type !== "event") continue;
|
|
708
763
|
const event = entry.event;
|
|
709
764
|
if (event.type !== "fallbacks/switch") continue;
|
|
710
765
|
switches.push({
|
|
@@ -874,7 +929,7 @@ window.__ModuleLoader__.load({
|
|
|
874
929
|
api;
|
|
875
930
|
rpc;
|
|
876
931
|
/** Snapshot consumed by the section through `useSyncExternalStore`. */
|
|
877
|
-
store = (0,
|
|
932
|
+
store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
|
|
878
933
|
status: "idle",
|
|
879
934
|
error: null,
|
|
880
935
|
writable: false,
|
|
@@ -890,7 +945,8 @@ window.__ModuleLoader__.load({
|
|
|
890
945
|
catalogEpoch: 0,
|
|
891
946
|
switchesStatus: "idle",
|
|
892
947
|
switchesError: null,
|
|
893
|
-
switches: []
|
|
948
|
+
switches: [],
|
|
949
|
+
subagentPolicy: void 0
|
|
894
950
|
});
|
|
895
951
|
/** Read guard: a newer load() supersedes an older one's publish. */
|
|
896
952
|
readGeneration = 0;
|
|
@@ -906,8 +962,18 @@ window.__ModuleLoader__.load({
|
|
|
906
962
|
namespaces = /* @__PURE__ */ new Map();
|
|
907
963
|
currentSession;
|
|
908
964
|
/**
|
|
909
|
-
*
|
|
910
|
-
*
|
|
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.
|
|
911
977
|
* @param rpc - the connection's generic RPC caller for the host gateway
|
|
912
978
|
* channel (`/api`), injected from the connection handle.
|
|
913
979
|
*/
|
|
@@ -937,12 +1003,12 @@ window.__ModuleLoader__.load({
|
|
|
937
1003
|
state.error = null;
|
|
938
1004
|
});
|
|
939
1005
|
try {
|
|
940
|
-
const [describeResult, getResult] = await Promise.all([this.api.settings.describe(
|
|
1006
|
+
const [describeResult, getResult] = await Promise.all([this.api.settings.describe(), this.rpc.call("/api", "fallbacks/get", { args: {} }).catch(() => void 0)]);
|
|
941
1007
|
if (generation !== this.readGeneration) return;
|
|
942
1008
|
if (writeGenerationAtStart !== this.writeGeneration) return;
|
|
943
|
-
if (!describeResult.
|
|
944
|
-
this.namespaces = new Map(describeResult.
|
|
945
|
-
const writable = describeResult.
|
|
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;
|
|
946
1012
|
let config;
|
|
947
1013
|
let legacyKeys = [];
|
|
948
1014
|
let seeds = [];
|
|
@@ -954,7 +1020,8 @@ window.__ModuleLoader__.load({
|
|
|
954
1020
|
}
|
|
955
1021
|
if ("seeds" in getResult.value) seeds = parseSeedsWire(getResult.value.seeds);
|
|
956
1022
|
}
|
|
957
|
-
|
|
1023
|
+
const subagentPolicy = getResult !== void 0 && getResult.ok ? subagentPolicyFromWire(getResult.value, void 0) : void 0;
|
|
1024
|
+
this.accept(config, writable, legacyKeys, seeds, subagentPolicy);
|
|
958
1025
|
} catch (error) {
|
|
959
1026
|
if (generation !== this.readGeneration) return;
|
|
960
1027
|
if (writeGenerationAtStart !== this.writeGeneration) return;
|
|
@@ -962,7 +1029,8 @@ window.__ModuleLoader__.load({
|
|
|
962
1029
|
}
|
|
963
1030
|
}
|
|
964
1031
|
/**
|
|
965
|
-
* Refresh the provider/model catalog (`llm
|
|
1032
|
+
* Refresh the provider/model catalog (`llm/listConfigurableProviders` +
|
|
1033
|
+
* `session/modelCatalog`), an
|
|
966
1034
|
* independent read path with its own generation guard so it can run
|
|
967
1035
|
* parallel to {@link load} without clobbering it (spec §2.5 D-4).
|
|
968
1036
|
* Per-provider lookup failures ride `catalogError` as a diagnostic without
|
|
@@ -977,13 +1045,13 @@ window.__ModuleLoader__.load({
|
|
|
977
1045
|
state.catalogError = null;
|
|
978
1046
|
});
|
|
979
1047
|
try {
|
|
980
|
-
const [providersResponse,
|
|
1048
|
+
const [providersResponse, catalogResponse] = await Promise.all([this.api.llm.listConfigurableProviders(), this.api.session.modelCatalog()]);
|
|
981
1049
|
if (generation !== this.catalogGeneration) return;
|
|
982
|
-
if (!providersResponse.
|
|
983
|
-
if (!
|
|
984
|
-
const providers = providersResponse.
|
|
985
|
-
const groups =
|
|
986
|
-
const 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;
|
|
987
1055
|
this.store.update((state) => {
|
|
988
1056
|
state.catalogStatus = "ready";
|
|
989
1057
|
state.catalogError = failures.length > 0 ? failures.map((failure) => `${failure.name}: ${failure.message}`).join("; ") : null;
|
|
@@ -1016,7 +1084,10 @@ window.__ModuleLoader__.load({
|
|
|
1016
1084
|
}
|
|
1017
1085
|
/**
|
|
1018
1086
|
* Read the recent-switch summary for the current session (spec §2.5 D-5):
|
|
1019
|
-
* one
|
|
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 —
|
|
1020
1091
|
* `fallbacks/switch` events extracted newest-first capped at
|
|
1021
1092
|
* {@link RECENT_SWITCH_LIMIT}. No current session → honest empty ready
|
|
1022
1093
|
* state (no RPC); a read failure lands `switchesStatus: 'error'` and never
|
|
@@ -1039,13 +1110,22 @@ window.__ModuleLoader__.load({
|
|
|
1039
1110
|
state.switchesError = null;
|
|
1040
1111
|
});
|
|
1041
1112
|
try {
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1113
|
+
const iterator = this.api.session.follow({
|
|
1114
|
+
address: {
|
|
1115
|
+
kind: "session",
|
|
1116
|
+
sessionId
|
|
1117
|
+
},
|
|
1044
1118
|
maxMessages: 50
|
|
1045
|
-
});
|
|
1119
|
+
}, this.followAbort.signal)[Symbol.asyncIterator]();
|
|
1120
|
+
let first;
|
|
1121
|
+
try {
|
|
1122
|
+
first = await iterator.next();
|
|
1123
|
+
} finally {
|
|
1124
|
+
await iterator.return?.();
|
|
1125
|
+
}
|
|
1046
1126
|
if (generation !== this.switchesGeneration) return;
|
|
1047
|
-
if (
|
|
1048
|
-
const switches = extractRecentSwitches(
|
|
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);
|
|
1049
1129
|
this.store.update((state) => {
|
|
1050
1130
|
state.switchesStatus = "ready";
|
|
1051
1131
|
state.switchesError = null;
|
|
@@ -1095,7 +1175,8 @@ window.__ModuleLoader__.load({
|
|
|
1095
1175
|
const wireSeeds = value.seeds;
|
|
1096
1176
|
if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
|
|
1097
1177
|
}
|
|
1098
|
-
|
|
1178
|
+
const subagentPolicy = subagentPolicyFromWire(value, this.store.getSnapshot().subagentPolicy);
|
|
1179
|
+
this.accept(config, true, legacyKeys, seeds, subagentPolicy);
|
|
1099
1180
|
} catch (error) {
|
|
1100
1181
|
if (generation !== this.writeGeneration) return;
|
|
1101
1182
|
this.fail(error);
|
|
@@ -1131,7 +1212,8 @@ window.__ModuleLoader__.load({
|
|
|
1131
1212
|
const wireSeeds = value.seeds;
|
|
1132
1213
|
if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
|
|
1133
1214
|
}
|
|
1134
|
-
|
|
1215
|
+
const subagentPolicy = subagentPolicyFromWire(value, this.store.getSnapshot().subagentPolicy);
|
|
1216
|
+
this.accept(config, true, legacyKeys, seeds, subagentPolicy);
|
|
1135
1217
|
} catch (error) {
|
|
1136
1218
|
if (generation !== this.writeGeneration) return;
|
|
1137
1219
|
this.fail(error);
|
|
@@ -1179,7 +1261,8 @@ window.__ModuleLoader__.load({
|
|
|
1179
1261
|
const wireSeeds = value.seeds;
|
|
1180
1262
|
if (Array.isArray(wireSeeds)) seeds = parseSeedsWire(wireSeeds);
|
|
1181
1263
|
}
|
|
1182
|
-
|
|
1264
|
+
const subagentPolicy = subagentPolicyFromWire(value, this.store.getSnapshot().subagentPolicy);
|
|
1265
|
+
this.accept(config, true, legacyKeys, seeds, subagentPolicy);
|
|
1183
1266
|
return revertOutcomePersona(value);
|
|
1184
1267
|
} catch (error) {
|
|
1185
1268
|
if (generation !== this.writeGeneration) return void 0;
|
|
@@ -1194,6 +1277,7 @@ window.__ModuleLoader__.load({
|
|
|
1194
1277
|
this.catalogGeneration += 1;
|
|
1195
1278
|
this.switchesGeneration += 1;
|
|
1196
1279
|
this.namespaces = /* @__PURE__ */ new Map();
|
|
1280
|
+
this.followAbort.abort();
|
|
1197
1281
|
}
|
|
1198
1282
|
/**
|
|
1199
1283
|
* Publish a settled load: `status` ready, `writable` from describe, and —
|
|
@@ -1211,7 +1295,7 @@ window.__ModuleLoader__.load({
|
|
|
1211
1295
|
* only when a real config resolved — a transient channel-down keeps the
|
|
1212
1296
|
* last accepted badge state.
|
|
1213
1297
|
*/
|
|
1214
|
-
accept(config, writable, legacyKeys, seeds) {
|
|
1298
|
+
accept(config, writable, legacyKeys, seeds, subagentPolicy) {
|
|
1215
1299
|
const parsed = config === void 0 ? void 0 : parseFallbacksConfig(config);
|
|
1216
1300
|
this.store.update((state) => {
|
|
1217
1301
|
state.status = "ready";
|
|
@@ -1220,6 +1304,7 @@ window.__ModuleLoader__.load({
|
|
|
1220
1304
|
state.present = parsed !== void 0;
|
|
1221
1305
|
state.legacyKeys = parsed === void 0 ? state.legacyKeys : legacyKeys;
|
|
1222
1306
|
state.seeds = parsed === void 0 ? state.seeds : seeds;
|
|
1307
|
+
state.subagentPolicy = parsed === void 0 ? state.subagentPolicy : subagentPolicy;
|
|
1223
1308
|
if (parsed !== void 0) state.config = parsed;
|
|
1224
1309
|
state.configuredProviders = configuredProvidersOf(state.providers, this.namespaces);
|
|
1225
1310
|
});
|
|
@@ -1323,6 +1408,13 @@ window.__ModuleLoader__.load({
|
|
|
1323
1408
|
"chains.selector.noModelsStrict": "该 provider 暂无可用模型(目录查询失败),请改选其他 provider。",
|
|
1324
1409
|
"mainAgent.label": "主代理",
|
|
1325
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": "策略存在但无法读取 — 插件切换已禁用",
|
|
1326
1418
|
"timeSlots.label": "分时槽设置",
|
|
1327
1419
|
"timeSlots.hint": "自上而下第一条命中生效;全时段行固定最后",
|
|
1328
1420
|
"timeSlots.tz.label": "时区(UTC±)",
|
|
@@ -1508,6 +1600,13 @@ window.__ModuleLoader__.load({
|
|
|
1508
1600
|
"chains.selector.noModelsStrict": "No models available for this provider (catalog lookup failed); pick another provider.",
|
|
1509
1601
|
"mainAgent.label": "Main agent",
|
|
1510
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",
|
|
1511
1610
|
"timeSlots.label": "Time slots",
|
|
1512
1611
|
"timeSlots.hint": "First match from top to bottom wins; the all-day row is always last",
|
|
1513
1612
|
"timeSlots.tz.label": "Timezone (UTC±)",
|
|
@@ -1680,7 +1779,7 @@ window.__ModuleLoader__.load({
|
|
|
1680
1779
|
}
|
|
1681
1780
|
//#endregion
|
|
1682
1781
|
//#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/FallbacksCard.module.css.mjs
|
|
1683
|
-
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";
|
|
1684
1783
|
const tagId$2 = "dsh-llm-fallbacks/FallbacksCard.module.css";
|
|
1685
1784
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
1686
1785
|
const tag = document.createElement("style");
|
|
@@ -1764,7 +1863,11 @@ window.__ModuleLoader__.load({
|
|
|
1764
1863
|
"statusTitle": "_d4f70367_statusTitle",
|
|
1765
1864
|
"statusLine": "_8ab300ed_statusLine",
|
|
1766
1865
|
"statusLineLabel": "_e8cedbf5_statusLineLabel",
|
|
1767
|
-
"offNotice": "_b48dfcba_offNotice"
|
|
1866
|
+
"offNotice": "_b48dfcba_offNotice",
|
|
1867
|
+
"policyStatus": "_700006c9_policyStatus",
|
|
1868
|
+
"policyStatusLabel": "_d4b67a81_policyStatusLabel",
|
|
1869
|
+
"policyStatusLine": "_278bb4b3_policyStatusLine",
|
|
1870
|
+
"policyStatusWarn": "_da6387e5_policyStatusWarn"
|
|
1768
1871
|
};
|
|
1769
1872
|
//#endregion
|
|
1770
1873
|
//#region src/client/FallbacksCard.tsx
|
|
@@ -3378,6 +3481,38 @@ window.__ModuleLoader__.load({
|
|
|
3378
3481
|
role: "alert",
|
|
3379
3482
|
children: t("error.generic", { message: state.error })
|
|
3380
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
|
+
}),
|
|
3381
3516
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3382
3517
|
className: FallbacksCard_module_css_default.field,
|
|
3383
3518
|
role: "group",
|
|
@@ -4343,12 +4478,12 @@ window.__ModuleLoader__.load({
|
|
|
4343
4478
|
//#region src/client/index.ts
|
|
4344
4479
|
/**
|
|
4345
4480
|
* Required services (cordis fiber inject); registrations wait on the slot
|
|
4346
|
-
* declaration. `
|
|
4347
|
-
* registration reads the service directly (`ctx.
|
|
4481
|
+
* declaration. `uiConversation` is declared because the D1 Definition
|
|
4482
|
+
* registration reads the service directly (`ctx.uiConversation.events.register`
|
|
4348
4483
|
* at the bottom of `apply` — explicit fiber-ordering parity with the
|
|
4349
4484
|
* ui-workflow-run precedent, whose inject list includes it for the same
|
|
4350
|
-
* direct read).
|
|
4351
|
-
*
|
|
4485
|
+
* direct read). Cordis would still provide the service synchronously on
|
|
4486
|
+
* apply, but the declaration makes the dependency honest. `sessions` is
|
|
4352
4487
|
* deliberately NOT injected (S-g): a non-web host without the dsh-session
|
|
4353
4488
|
* client service must not hang the fiber waiting for it — the wiring reads
|
|
4354
4489
|
* it reflectively and degrades to the switches empty state when absent
|
|
@@ -4360,7 +4495,7 @@ window.__ModuleLoader__.load({
|
|
|
4360
4495
|
"locale",
|
|
4361
4496
|
"connection",
|
|
4362
4497
|
"remote",
|
|
4363
|
-
"
|
|
4498
|
+
"uiConversation"
|
|
4364
4499
|
];
|
|
4365
4500
|
/**
|
|
4366
4501
|
* Register the `fallbacks` dictionaries and the plugin-config card once the
|
|
@@ -4374,7 +4509,7 @@ window.__ModuleLoader__.load({
|
|
|
4374
4509
|
}), "llm-fallbacks: dictionaries");
|
|
4375
4510
|
const connection = ctx.get("connection");
|
|
4376
4511
|
const sessions = ctx.get("sessions");
|
|
4377
|
-
const controller = new FallbacksSettingsController(
|
|
4512
|
+
const controller = new FallbacksSettingsController(ctx.remote, connection.rpc);
|
|
4378
4513
|
const useSnapshot = bindSnapshotSelector(controller.store);
|
|
4379
4514
|
ctx.effect(() => {
|
|
4380
4515
|
const syncSession = () => {
|
|
@@ -4438,7 +4573,7 @@ window.__ModuleLoader__.load({
|
|
|
4438
4573
|
})
|
|
4439
4574
|
}, GeneralFallbacksRow);
|
|
4440
4575
|
});
|
|
4441
|
-
ctx.effect(() => ctx.
|
|
4576
|
+
ctx.effect(() => ctx.uiConversation.events.register(fallbackSwitchDefinition), "llm-fallbacks: conversation node definition");
|
|
4442
4577
|
ctx.slots.inject("conversation.chat.node", function* () {
|
|
4443
4578
|
yield ctx.slots.register({
|
|
4444
4579
|
name: "conversation.chat.node",
|
package/dist/client/locales.d.ts
CHANGED
|
@@ -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;
|
package/dist/commands.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ export interface FallbacksCooldownEntry {
|
|
|
57
57
|
readonly key: string;
|
|
58
58
|
/** Expiry epoch ms; `Infinity` for `revertPolicy: 'never'`. */
|
|
59
59
|
readonly untilEpochMs: number;
|
|
60
|
+
/** True for a half-open marker row (an expired cooldown awaiting a recovery probe). */
|
|
61
|
+
readonly halfOpen?: boolean;
|
|
60
62
|
}
|
|
61
63
|
/** The read-only diagnostic snapshot the `/fallbacks` handler renders. */
|
|
62
64
|
export interface FallbacksCommandSnapshot {
|
|
@@ -192,6 +194,7 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
192
194
|
readonly cooldownNone: "无活跃冷却";
|
|
193
195
|
readonly cooldownLine: "{key} 冷却至 {time}";
|
|
194
196
|
readonly cooldownNever: "{key} 会话内不再回主";
|
|
197
|
+
readonly cooldownHalfOpen: "{key} half-open(等待恢复探针)";
|
|
195
198
|
readonly reason: {
|
|
196
199
|
readonly 'trigger-code': "触发码";
|
|
197
200
|
readonly 'always-cap': "always 上限";
|
|
@@ -246,6 +249,7 @@ export declare const FALLBACKS_COMMAND_LOCALES: {
|
|
|
246
249
|
readonly cooldownNone: "none active";
|
|
247
250
|
readonly cooldownLine: "{key} suppressed until {time}";
|
|
248
251
|
readonly cooldownNever: "{key} not reverting this session";
|
|
252
|
+
readonly cooldownHalfOpen: "{key} half-open (awaiting recovery probe)";
|
|
249
253
|
readonly reason: {
|
|
250
254
|
readonly 'trigger-code': "trigger-code";
|
|
251
255
|
readonly 'always-cap': "always-cap";
|
package/dist/config.d.ts
CHANGED
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
* @module dsh-llm-fallbacks/config
|
|
29
29
|
*/
|
|
30
30
|
import type { SlotRowConfig } from './time-slots.ts';
|
|
31
|
+
/** How an expired cooldown recovers the route (plan fallbacks-half-open-recovery Task 1). */
|
|
32
|
+
export type RecoveryPolicy = 'timer' | 'half-open';
|
|
31
33
|
/** How a cooled-down model comes back (spec §4). */
|
|
32
34
|
export type RevertPolicy = 'cooldown-expiry' | 'never';
|
|
33
35
|
/** A single role rule: match on provider/model patterns (spec §3). */
|
|
@@ -125,6 +127,18 @@ export interface FallbacksConfig {
|
|
|
125
127
|
* UTC+8). Not per-slot.
|
|
126
128
|
*/
|
|
127
129
|
tz?: string;
|
|
130
|
+
/**
|
|
131
|
+
* Cooldown-expiry recovery mode (plan fallbacks-half-open-recovery Task
|
|
132
|
+
* 1): `'timer'` restores the preferred candidate when the cooldown
|
|
133
|
+
* expires (today's behavior); `'half-open'` leaves the route half-open
|
|
134
|
+
* for one logged probe instead. Optional on purpose, mirroring
|
|
135
|
+
* `presets` — a required field would break library consumers that
|
|
136
|
+
* construct `FallbacksConfig` literals with the existing keys
|
|
137
|
+
* (additive, non-breaking). The value domain is guarded by the schema
|
|
138
|
+
* (`Config` in `src/schema.ts`), NOT by `validateFallbacksConfig`, and
|
|
139
|
+
* every resolved config carries a value via the schema default.
|
|
140
|
+
*/
|
|
141
|
+
recovery?: RecoveryPolicy;
|
|
128
142
|
}
|
|
129
143
|
/**
|
|
130
144
|
* Spec §4 defaults — `Config({})` must equal this (no-op install).
|
package/dist/cooldown.d.ts
CHANGED
|
@@ -24,6 +24,15 @@ export declare class CooldownStore {
|
|
|
24
24
|
suppress(key: string, untilEpochMs: number): void;
|
|
25
25
|
/** True while `key` is suppressed at time `now` (default `Date.now()`); expired entries are removed. */
|
|
26
26
|
isSuppressed(key: string, now?: number): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Raw expiry read — no lazy drop (plan fallbacks-half-open-recovery P2
|
|
29
|
+
* rule 3). `undefined` for unknown keys; `Infinity` for
|
|
30
|
+
* `revertPolicy: 'never'` entries. The half-open read path uses this to
|
|
31
|
+
* observe the lapsed `until` before the decision-path drop.
|
|
32
|
+
*/
|
|
33
|
+
peek(key: string): number | undefined;
|
|
34
|
+
/** Unfiltered map keys, in insertion order (plan P4 display sync). */
|
|
35
|
+
keys(): IterableIterator<string>;
|
|
27
36
|
/**
|
|
28
37
|
* Read-only diagnostic accessor: the active (non-expired) entries, in
|
|
29
38
|
* insertion order. This is a pure read — expired entries are FILTERED OUT
|