@mars-sea/dsh-commandcode-provider 0.12.1 → 0.12.2
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/CHANGELOG.md +29 -0
- package/README.md +5 -1
- package/README.zh-CN.md +6 -1
- package/lib/client.js +245 -69
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +67 -16
- package/lib/index.js +367 -175
- package/lib/index.js.map +1 -1
- package/package.json +40 -40
package/lib/client.js
CHANGED
|
@@ -36,6 +36,38 @@ window.__ModuleLoader__.load({
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
//#endregion
|
|
39
|
+
//#region src/client/error-text.ts
|
|
40
|
+
/**
|
|
41
|
+
* Turn a caught value into readable text for the settings page's error UI.
|
|
42
|
+
*
|
|
43
|
+
* @module dsh-commandcode-provider/client/error-text
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* `error instanceof Error ? error.message : String(error)` degrades to the
|
|
47
|
+
* literal string `[object Object]` for a plain object with no `Error`
|
|
48
|
+
* prototype — which is exactly what a Remote call across the webview/host
|
|
49
|
+
* boundary can hand back: `dsh-typert-protocol` serializes a rejection for
|
|
50
|
+
* the wire, and a structurally-cloned value loses its prototype chain even
|
|
51
|
+
* when the host threw a real `Error` (issue #74). Reading a `message` string
|
|
52
|
+
* off the plain object first recovers the original text in that case; only a
|
|
53
|
+
* value with neither an `Error` prototype nor a usable `message` field falls
|
|
54
|
+
* through to a JSON dump.
|
|
55
|
+
*/
|
|
56
|
+
function readableErrorText(error) {
|
|
57
|
+
if (error instanceof Error) return error.message;
|
|
58
|
+
if (typeof error === "string") return error;
|
|
59
|
+
if (error !== null && typeof error === "object") {
|
|
60
|
+
const message = error.message;
|
|
61
|
+
if (typeof message === "string" && message !== "") return message;
|
|
62
|
+
try {
|
|
63
|
+
return JSON.stringify(error);
|
|
64
|
+
} catch {
|
|
65
|
+
return Object.prototype.toString.call(error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return String(error);
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
39
71
|
//#region src/client/settings-scope.ts
|
|
40
72
|
/**
|
|
41
73
|
* Backoff before re-reading a directory whose FIRST read failed, in millis.
|
|
@@ -169,7 +201,7 @@ window.__ModuleLoader__.load({
|
|
|
169
201
|
outcome = typeof value === "object" && value !== null ? { view: value } : { failure: "settings describe answered no view" };
|
|
170
202
|
} else outcome = { failure: response.error?.message ?? "settings describe failed" };
|
|
171
203
|
} catch (error) {
|
|
172
|
-
outcome = { failure:
|
|
204
|
+
outcome = { failure: readableErrorText(error) };
|
|
173
205
|
}
|
|
174
206
|
if (generation !== this.generation) continue;
|
|
175
207
|
if ("view" in outcome) {
|
|
@@ -310,7 +342,7 @@ window.__ModuleLoader__.load({
|
|
|
310
342
|
} catch (error) {
|
|
311
343
|
return {
|
|
312
344
|
ok: false,
|
|
313
|
-
error: { message:
|
|
345
|
+
error: { message: readableErrorText(error) }
|
|
314
346
|
};
|
|
315
347
|
}
|
|
316
348
|
}
|
|
@@ -417,6 +449,7 @@ window.__ModuleLoader__.load({
|
|
|
417
449
|
subscribe: (listener) => scope.subscribe(listener),
|
|
418
450
|
set: (field, value) => scope.set(field, value),
|
|
419
451
|
unset: (field) => scope.unset(field),
|
|
452
|
+
mutate: (ops, revision) => scope.mutate(ops, revision),
|
|
420
453
|
refresh: () => {
|
|
421
454
|
mirror.load();
|
|
422
455
|
},
|
|
@@ -428,6 +461,23 @@ window.__ModuleLoader__.load({
|
|
|
428
461
|
};
|
|
429
462
|
}
|
|
430
463
|
//#endregion
|
|
464
|
+
//#region src/timeout-limits.ts
|
|
465
|
+
/** 两端共用可编辑超时范围,存储仍是整数毫秒;提示不能借用重试退避上限。 */
|
|
466
|
+
const MIN_TIMEOUT_SECONDS = .001;
|
|
467
|
+
const MAX_TIMEOUT_SECONDS = 3600;
|
|
468
|
+
//#endregion
|
|
469
|
+
//#region src/model-visibility.ts
|
|
470
|
+
/** 网页、终端与模型目录共用的选择规则;显式开关优先于白名单。 */
|
|
471
|
+
function modelIsVisible(id, allowlist, overrides) {
|
|
472
|
+
const flag = overrides !== null && typeof overrides === "object" && !Array.isArray(overrides) ? overrides[id] : void 0;
|
|
473
|
+
return typeof flag === "boolean" ? flag : allowlist.length === 0 || allowlist.includes(id);
|
|
474
|
+
}
|
|
475
|
+
/** 只接收布尔事实,手工配置中的其他值不能成为可见性开关。 */
|
|
476
|
+
function readVisibility(raw) {
|
|
477
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return {};
|
|
478
|
+
return Object.fromEntries(Object.entries(raw).filter(([id, value]) => id !== "" && typeof value === "boolean"));
|
|
479
|
+
}
|
|
480
|
+
//#endregion
|
|
431
481
|
//#region src/client/settings.ts
|
|
432
482
|
/**
|
|
433
483
|
* Browser controller for the "Command Code" settings page (a `settings.section`
|
|
@@ -526,28 +576,25 @@ window.__ModuleLoader__.load({
|
|
|
526
576
|
}
|
|
527
577
|
};
|
|
528
578
|
}
|
|
529
|
-
const MAX_TIMEOUT_SECONDS = 3600;
|
|
530
579
|
/**
|
|
531
|
-
*
|
|
580
|
+
* 秒制输入保留毫秒精度,兼容已有 1500ms、1ms 等配置。
|
|
532
581
|
*
|
|
533
582
|
* Milliseconds are the wrong unit to show: the defaults are 300000 and the
|
|
534
583
|
* ceiling is 2147483647, so the page asked users to do arithmetic to answer
|
|
535
584
|
* "how long is a reasonable wait". `format` divides, `parse` multiplies, and
|
|
536
585
|
* the stored value never leaves milliseconds.
|
|
537
586
|
*
|
|
538
|
-
*
|
|
539
|
-
* not accept, and silently storing 1000 or 2000 for it would make the saved
|
|
540
|
-
* profile disagree with the box it was typed in.
|
|
587
|
+
* 最多三位小数;不接受更多位数后悄悄取整,避免页面与存储不一致。
|
|
541
588
|
*/
|
|
542
589
|
function secondsField(field, bounds) {
|
|
543
590
|
return {
|
|
544
591
|
field,
|
|
545
|
-
format: (value) => typeof value === "number" ? String(
|
|
592
|
+
format: (value) => typeof value === "number" ? String(value / 1e3) : "",
|
|
546
593
|
parse: (text) => {
|
|
547
594
|
const trimmed = text.trim();
|
|
548
595
|
if (trimmed === "") return { kind: "clear" };
|
|
549
596
|
const parsed = Number(trimmed);
|
|
550
|
-
if (!Number.isFinite(parsed) ||
|
|
597
|
+
if (!Number.isFinite(parsed) || !/^-?(?:\d+(?:\.\d{1,3})?|\.\d{1,3})$/.test(trimmed)) return {
|
|
551
598
|
kind: "invalid",
|
|
552
599
|
reason: "format"
|
|
553
600
|
};
|
|
@@ -561,7 +608,7 @@ window.__ModuleLoader__.load({
|
|
|
561
608
|
};
|
|
562
609
|
return {
|
|
563
610
|
kind: "set",
|
|
564
|
-
value: parsed * 1e3
|
|
611
|
+
value: Math.round(parsed * 1e3)
|
|
565
612
|
};
|
|
566
613
|
}
|
|
567
614
|
};
|
|
@@ -570,11 +617,11 @@ window.__ModuleLoader__.load({
|
|
|
570
617
|
const SECTION_FIELDS = [
|
|
571
618
|
textField("apiBase"),
|
|
572
619
|
secondsField("requestTimeoutMs", {
|
|
573
|
-
min:
|
|
620
|
+
min: MIN_TIMEOUT_SECONDS,
|
|
574
621
|
max: MAX_TIMEOUT_SECONDS
|
|
575
622
|
}),
|
|
576
623
|
secondsField("streamIdleTimeoutMs", {
|
|
577
|
-
min:
|
|
624
|
+
min: MIN_TIMEOUT_SECONDS,
|
|
578
625
|
max: MAX_TIMEOUT_SECONDS
|
|
579
626
|
}),
|
|
580
627
|
numberField$1("transportMaxRetries", {
|
|
@@ -726,7 +773,9 @@ window.__ModuleLoader__.load({
|
|
|
726
773
|
accountModels: Object.fromEntries(accountModelMap(this.storedRules())),
|
|
727
774
|
accountBusy: this.accountPending > 0,
|
|
728
775
|
accountFailed: this.accountFailed,
|
|
776
|
+
pendingCredentialCleanup: this.cleanupRefs(),
|
|
729
777
|
visibleModels: this.effectiveVisibleModels(),
|
|
778
|
+
visibleModelsAll: this.visibleModelsDraft === void 0 ? this.storedShowsAll() : this.visibleModelsDraft.length === 0,
|
|
730
779
|
catalogModels: this.catalogModels,
|
|
731
780
|
catalogFailed: this.catalogFailed,
|
|
732
781
|
dirty: plan.length > 0 || this.visibleModelsDirty(),
|
|
@@ -780,6 +829,8 @@ window.__ModuleLoader__.load({
|
|
|
780
829
|
}
|
|
781
830
|
/** Write every staged edit, then re-read the Host's accepted state. */
|
|
782
831
|
async save() {
|
|
832
|
+
const submitted = new Map(this.staged);
|
|
833
|
+
const submittedVisible = this.visibleModelsDraft;
|
|
783
834
|
const plan = this.plan();
|
|
784
835
|
const visibleRuns = this.visibleModelsPlan();
|
|
785
836
|
if (plan.length === 0 && visibleRuns.length === 0 || this.saving) return;
|
|
@@ -808,8 +859,8 @@ window.__ModuleLoader__.load({
|
|
|
808
859
|
this.failed = !landed;
|
|
809
860
|
if (landed) {
|
|
810
861
|
this.savedCount += 1;
|
|
811
|
-
this.staged.
|
|
812
|
-
this.visibleModelsDraft = void 0;
|
|
862
|
+
for (const [field, draft] of submitted) if (this.staged.get(field) === draft) this.staged.delete(field);
|
|
863
|
+
if (this.visibleModelsDraft === submittedVisible) this.visibleModelsDraft = void 0;
|
|
813
864
|
} else this.reconcileStaging();
|
|
814
865
|
this.publish();
|
|
815
866
|
}
|
|
@@ -869,23 +920,74 @@ window.__ModuleLoader__.load({
|
|
|
869
920
|
});
|
|
870
921
|
}
|
|
871
922
|
/**
|
|
872
|
-
*
|
|
873
|
-
*
|
|
923
|
+
* 账户、路由、固定账户与清理队列一起提交;随后才删密钥。
|
|
924
|
+
* 跨服务不能构造事务,持久化队列让中断或凭据失败后仍可重试。
|
|
874
925
|
*/
|
|
875
926
|
removeAccount(ref) {
|
|
876
927
|
return this.runAccountOp("remove", async () => {
|
|
877
|
-
if (this.
|
|
928
|
+
if (this.scope.mutate === void 0) return false;
|
|
929
|
+
if (!this.rawStoredAccounts().some((entry) => entry.apiKeyEnv === ref) && !this.cleanupRefs().includes(ref)) return false;
|
|
930
|
+
const snapshot = this.scope.getSnapshot();
|
|
878
931
|
const list = this.rawStoredAccounts().filter((entry) => entry.apiKeyEnv !== ref).map((entry) => ({ ...entry }));
|
|
879
|
-
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
932
|
+
const rules = this.storedRules().filter((rule) => rule.account !== ref);
|
|
933
|
+
const cleanup = [.../* @__PURE__ */ new Set([...this.cleanupRefs(), ref])];
|
|
934
|
+
const ops = [
|
|
935
|
+
{
|
|
936
|
+
op: "set",
|
|
937
|
+
path: ["accounts"],
|
|
938
|
+
value: list
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
op: "set",
|
|
942
|
+
path: ["modelAccountRules"],
|
|
943
|
+
value: rules
|
|
944
|
+
},
|
|
945
|
+
{
|
|
946
|
+
op: "set",
|
|
947
|
+
path: ["credentialCleanupRefs"],
|
|
948
|
+
value: cleanup
|
|
949
|
+
}
|
|
950
|
+
];
|
|
951
|
+
const pinned = this.sectionValue("activeAccount") === ref;
|
|
952
|
+
if (pinned) ops.push(this.baseValue("activeAccount") === ref ? {
|
|
953
|
+
op: "set",
|
|
954
|
+
path: ["activeAccount"],
|
|
955
|
+
value: ""
|
|
956
|
+
} : {
|
|
957
|
+
op: "unset",
|
|
958
|
+
path: ["activeAccount"]
|
|
959
|
+
});
|
|
960
|
+
await this.scope.mutate(ops, snapshot.revision);
|
|
961
|
+
if (this.rawStoredAccounts().some((entry) => entry.apiKeyEnv === ref) || this.storedRules().some((rule) => rule.account === ref) || pinned && this.sectionValue("activeAccount") === ref || !this.cleanupRefs().includes(ref)) return false;
|
|
962
|
+
return this.cleanRemovedCredential(ref);
|
|
887
963
|
});
|
|
888
964
|
}
|
|
965
|
+
/** 清理重试不能再次删除同名新账户,配置移除与凭据清理分开调用。 */
|
|
966
|
+
retryCredentialCleanup(ref) {
|
|
967
|
+
return this.runAccountOp("remove", () => this.cleanRemovedCredential(ref));
|
|
968
|
+
}
|
|
969
|
+
async cleanRemovedCredential(ref) {
|
|
970
|
+
if (!this.cleanupRefs().includes(ref) || this.scope.mutate === void 0) return false;
|
|
971
|
+
if (!await this.describeAll([ref])) return false;
|
|
972
|
+
const baseAccounts = this.baseValue("accounts");
|
|
973
|
+
const inherited = Array.isArray(baseAccounts) && baseAccounts.some((entry) => typeof entry === "object" && entry !== null && entry.apiKeyEnv === ref);
|
|
974
|
+
if (!(ref === this.credentialRef || inherited || this.rawStoredAccounts().some((entry) => entry.apiKeyEnv === ref) || this.storedRules().some((rule) => rule.account === ref) || this.sectionValue("activeAccount") === ref) && this.credentialStates.get(ref)?.configured === true && !await this.unsetKey(ref)) return false;
|
|
975
|
+
return this.finishCleanup(ref);
|
|
976
|
+
}
|
|
977
|
+
cleanupRefs() {
|
|
978
|
+
const raw = this.sectionValue("credentialCleanupRefs");
|
|
979
|
+
return Array.isArray(raw) ? [...new Set(raw.filter((ref) => typeof ref === "string" && ref !== ""))] : [];
|
|
980
|
+
}
|
|
981
|
+
async finishCleanup(ref) {
|
|
982
|
+
const snapshot = this.scope.getSnapshot();
|
|
983
|
+
const refs = this.cleanupRefs().filter((entry) => entry !== ref);
|
|
984
|
+
await this.scope.mutate?.([{
|
|
985
|
+
op: "set",
|
|
986
|
+
path: ["credentialCleanupRefs"],
|
|
987
|
+
value: refs
|
|
988
|
+
}], snapshot.revision);
|
|
989
|
+
return !this.cleanupRefs().includes(ref);
|
|
990
|
+
}
|
|
889
991
|
/** Store a replacement key now; `target` is `'default'` or an extra account's reference. */
|
|
890
992
|
setAccountKey(target, key) {
|
|
891
993
|
const value = key.trim();
|
|
@@ -1037,7 +1139,7 @@ window.__ModuleLoader__.load({
|
|
|
1037
1139
|
if (field === "apiKey" || staged.clear) continue;
|
|
1038
1140
|
if (staged.text === this.spec(field).format(this.sectionValue(field))) this.staged.delete(field);
|
|
1039
1141
|
}
|
|
1040
|
-
if (this.visibleModelsDraft !== void 0 &&
|
|
1142
|
+
if (this.visibleModelsDraft !== void 0 && !this.visibleModelsDirty()) this.visibleModelsDraft = void 0;
|
|
1041
1143
|
}
|
|
1042
1144
|
async clear(field) {
|
|
1043
1145
|
if (!this.stored(field)) return true;
|
|
@@ -1082,9 +1184,10 @@ window.__ModuleLoader__.load({
|
|
|
1082
1184
|
try {
|
|
1083
1185
|
response = await this.api.credentials.describe(refs);
|
|
1084
1186
|
} catch {
|
|
1085
|
-
return;
|
|
1187
|
+
return false;
|
|
1086
1188
|
}
|
|
1087
|
-
if (!response.ok) return;
|
|
1189
|
+
if (!response.ok) return false;
|
|
1190
|
+
if (extra.some((ref) => typeof response.value?.[ref]?.configured !== "boolean")) return false;
|
|
1088
1191
|
let changed = false;
|
|
1089
1192
|
for (const ref of refs) {
|
|
1090
1193
|
const view = response.value?.[ref];
|
|
@@ -1099,6 +1202,7 @@ window.__ModuleLoader__.load({
|
|
|
1099
1202
|
}
|
|
1100
1203
|
}
|
|
1101
1204
|
if (changed) this.publish();
|
|
1205
|
+
return true;
|
|
1102
1206
|
}
|
|
1103
1207
|
/**
|
|
1104
1208
|
* Fetch the model catalog through the Host Remote. Runs once at construction;
|
|
@@ -1200,24 +1304,61 @@ window.__ModuleLoader__.load({
|
|
|
1200
1304
|
const after = this.storedRules();
|
|
1201
1305
|
return after.length === list.length && list.every((item, index) => after[index] !== void 0 && sameModels(after[index].models, item.models) && after[index].account === item.account);
|
|
1202
1306
|
}
|
|
1203
|
-
/**
|
|
1204
|
-
|
|
1307
|
+
/** 原始白名单;空列表延续现有的显示全部语义。 */
|
|
1308
|
+
storedAllowlist() {
|
|
1205
1309
|
const raw = this.scope.getSnapshot().value?.visibleModels;
|
|
1206
1310
|
if (!Array.isArray(raw)) return [];
|
|
1207
1311
|
return raw.filter((m) => typeof m === "string" && m !== "");
|
|
1208
1312
|
}
|
|
1313
|
+
storedShowsAll() {
|
|
1314
|
+
return this.storedAllowlist().length === 0 && !Object.values(readVisibility(this.scope.getSnapshot().value?.modelVisibility)).includes(false);
|
|
1315
|
+
}
|
|
1316
|
+
/** 目录、白名单与显式显示的旧模型一起投影,目录失败不删除旧选择。 */
|
|
1317
|
+
storedVisibleModels() {
|
|
1318
|
+
const list = this.storedAllowlist();
|
|
1319
|
+
const flags = readVisibility(this.scope.getSnapshot().value?.modelVisibility);
|
|
1320
|
+
return [.../* @__PURE__ */ new Set([
|
|
1321
|
+
...list,
|
|
1322
|
+
...this.catalogModels.map((model) => model.id),
|
|
1323
|
+
...Object.keys(flags)
|
|
1324
|
+
])].filter((id) => modelIsVisible(id, list, flags));
|
|
1325
|
+
}
|
|
1209
1326
|
effectiveVisibleModels() {
|
|
1210
|
-
|
|
1327
|
+
if (this.visibleModelsDraft === void 0) return this.storedVisibleModels();
|
|
1328
|
+
return this.visibleModelsDraft.length === 0 ? this.catalogModels.map((model) => model.id) : this.visibleModelsDraft;
|
|
1211
1329
|
}
|
|
1212
1330
|
visibleModelsDirty() {
|
|
1213
|
-
|
|
1331
|
+
if (this.visibleModelsDraft === void 0) return false;
|
|
1332
|
+
if (this.visibleModelsDraft.length === 0) return !this.storedShowsAll();
|
|
1333
|
+
return this.storedShowsAll() || !sameModels(this.visibleModelsDraft, this.storedVisibleModels());
|
|
1214
1334
|
}
|
|
1215
1335
|
visibleModelsPlan() {
|
|
1216
1336
|
if (!this.visibleModelsDirty()) return [];
|
|
1337
|
+
const list = [...this.visibleModelsDraft ?? []];
|
|
1217
1338
|
return [async () => {
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1339
|
+
if (this.scope.mutate === void 0) return false;
|
|
1340
|
+
const snapshot = this.scope.getSnapshot();
|
|
1341
|
+
const layers = [
|
|
1342
|
+
snapshot.base,
|
|
1343
|
+
snapshot.user,
|
|
1344
|
+
snapshot.value
|
|
1345
|
+
];
|
|
1346
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1347
|
+
for (const layer of layers) {
|
|
1348
|
+
if (layer === null || typeof layer !== "object") continue;
|
|
1349
|
+
for (const id of Object.keys(readVisibility(layer.modelVisibility))) keys.add(id);
|
|
1350
|
+
}
|
|
1351
|
+
const flags = Object.fromEntries([...keys].map((id) => [id, list.length === 0 || list.includes(id)]));
|
|
1352
|
+
await this.scope.mutate([{
|
|
1353
|
+
op: "set",
|
|
1354
|
+
path: ["visibleModels"],
|
|
1355
|
+
value: list
|
|
1356
|
+
}, {
|
|
1357
|
+
op: "set",
|
|
1358
|
+
path: ["modelVisibility"],
|
|
1359
|
+
value: flags
|
|
1360
|
+
}], snapshot.revision);
|
|
1361
|
+
return list.length === 0 ? this.storedShowsAll() : sameModels(this.storedVisibleModels(), list);
|
|
1221
1362
|
}];
|
|
1222
1363
|
}
|
|
1223
1364
|
publish() {
|
|
@@ -1324,7 +1465,7 @@ window.__ModuleLoader__.load({
|
|
|
1324
1465
|
this.current = {
|
|
1325
1466
|
...this.current,
|
|
1326
1467
|
status: "error",
|
|
1327
|
-
error:
|
|
1468
|
+
error: readableErrorText(error)
|
|
1328
1469
|
};
|
|
1329
1470
|
} finally {
|
|
1330
1471
|
if (generation === this.generation) this.inFlight = false;
|
|
@@ -1458,7 +1599,7 @@ window.__ModuleLoader__.load({
|
|
|
1458
1599
|
this.publish({
|
|
1459
1600
|
status: "error",
|
|
1460
1601
|
table: void 0,
|
|
1461
|
-
error:
|
|
1602
|
+
error: readableErrorText(error)
|
|
1462
1603
|
});
|
|
1463
1604
|
this.scheduleRetry();
|
|
1464
1605
|
});
|
|
@@ -1578,7 +1719,7 @@ window.__ModuleLoader__.load({
|
|
|
1578
1719
|
} catch (error) {
|
|
1579
1720
|
result = {
|
|
1580
1721
|
ok: false,
|
|
1581
|
-
error: { message:
|
|
1722
|
+
error: { message: readableErrorText(error) }
|
|
1582
1723
|
};
|
|
1583
1724
|
}
|
|
1584
1725
|
if (this.superseded(generation)) return;
|
|
@@ -2262,7 +2403,7 @@ window.__ModuleLoader__.load({
|
|
|
2262
2403
|
}
|
|
2263
2404
|
//#endregion
|
|
2264
2405
|
//#region package.json
|
|
2265
|
-
var version = "0.12.
|
|
2406
|
+
var version = "0.12.2";
|
|
2266
2407
|
var repository = {
|
|
2267
2408
|
"type": "git",
|
|
2268
2409
|
"url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
|
|
@@ -2520,7 +2661,7 @@ window.__ModuleLoader__.load({
|
|
|
2520
2661
|
}) : null;
|
|
2521
2662
|
}
|
|
2522
2663
|
/** One text/number field row. */
|
|
2523
|
-
function Field({ id, label, hint, state, disabled, numeric, wide, placeholder, onEdit, onReset, t }) {
|
|
2664
|
+
function Field({ id, label, hint, state, disabled, numeric, decimal, wide, placeholder, onEdit, onReset, t }) {
|
|
2524
2665
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingRow, {
|
|
2525
2666
|
title: label,
|
|
2526
2667
|
titleFor: id,
|
|
@@ -2529,7 +2670,7 @@ window.__ModuleLoader__.load({
|
|
|
2529
2670
|
t
|
|
2530
2671
|
}),
|
|
2531
2672
|
description: hint,
|
|
2532
|
-
error: state.invalid ? invalidCopy(state.invalidReason, t) : void 0,
|
|
2673
|
+
error: state.invalid ? invalidCopy(state.invalidReason, t, decimal) : void 0,
|
|
2533
2674
|
control: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldOverride, {
|
|
2534
2675
|
label,
|
|
2535
2676
|
state,
|
|
@@ -2540,7 +2681,7 @@ window.__ModuleLoader__.load({
|
|
|
2540
2681
|
id,
|
|
2541
2682
|
className: `cc-input ${wide ? "cc-rowInputWide" : "cc-rowInput"}${state.invalid ? " cc-inputInvalid" : ""}`,
|
|
2542
2683
|
type: "text",
|
|
2543
|
-
inputMode: numeric ? "numeric" : void 0,
|
|
2684
|
+
inputMode: decimal ? "decimal" : numeric ? "numeric" : void 0,
|
|
2544
2685
|
"aria-invalid": state.invalid || void 0,
|
|
2545
2686
|
value: state.text,
|
|
2546
2687
|
placeholder,
|
|
@@ -2550,7 +2691,12 @@ window.__ModuleLoader__.load({
|
|
|
2550
2691
|
});
|
|
2551
2692
|
}
|
|
2552
2693
|
/** The per-field error copy for a staged draft's failure reason. */
|
|
2553
|
-
function invalidCopy(reason, t) {
|
|
2694
|
+
function invalidCopy(reason, t, duration = false) {
|
|
2695
|
+
if (duration) {
|
|
2696
|
+
if (reason === "tooSmall") return t("durationTooSmall");
|
|
2697
|
+
if (reason === "tooLarge") return t("durationTooLarge");
|
|
2698
|
+
return t("durationInvalid");
|
|
2699
|
+
}
|
|
2554
2700
|
if (reason === "tooSmall") return t("numberTooSmall");
|
|
2555
2701
|
if (reason === "tooLarge") return t("numberTooLarge");
|
|
2556
2702
|
return t("invalidNumber");
|
|
@@ -2923,8 +3069,7 @@ window.__ModuleLoader__.load({
|
|
|
2923
3069
|
function VisibleModelsRow({ t, state, disabled, onSelect, onClear }) {
|
|
2924
3070
|
const count = state.visibleModels.length;
|
|
2925
3071
|
const pickT = (key, params) => {
|
|
2926
|
-
if (key === "modelPick") return t("
|
|
2927
|
-
if (key === "modelCount") return t("visibleModelsCount", params);
|
|
3072
|
+
if (key === "modelPick" || key === "modelCount") return state.visibleModelsAll ? t("visibleModelsShowAll") : t("visibleModelsCount", { count });
|
|
2928
3073
|
return t(key, params);
|
|
2929
3074
|
};
|
|
2930
3075
|
const readiness = {
|
|
@@ -2946,7 +3091,7 @@ window.__ModuleLoader__.load({
|
|
|
2946
3091
|
onClick: () => onSelect(state.visibleModels.filter((id) => !staleIds.includes(id))),
|
|
2947
3092
|
children: t("visibleModelsCleanStale", { count: staleIds.length })
|
|
2948
3093
|
}) : null,
|
|
2949
|
-
|
|
3094
|
+
!state.visibleModelsAll ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2950
3095
|
type: "button",
|
|
2951
3096
|
className: "cc-linkButton",
|
|
2952
3097
|
disabled,
|
|
@@ -3127,6 +3272,7 @@ window.__ModuleLoader__.load({
|
|
|
3127
3272
|
state: state.requestTimeoutMs,
|
|
3128
3273
|
disabled,
|
|
3129
3274
|
numeric: true,
|
|
3275
|
+
decimal: true,
|
|
3130
3276
|
onEdit: (text) => onEdit("requestTimeoutMs", text),
|
|
3131
3277
|
onReset: () => onReset("requestTimeoutMs"),
|
|
3132
3278
|
t
|
|
@@ -3138,6 +3284,7 @@ window.__ModuleLoader__.load({
|
|
|
3138
3284
|
state: state.streamIdleTimeoutMs,
|
|
3139
3285
|
disabled,
|
|
3140
3286
|
numeric: true,
|
|
3287
|
+
decimal: true,
|
|
3141
3288
|
onEdit: (text) => onEdit("streamIdleTimeoutMs", text),
|
|
3142
3289
|
onReset: () => onReset("streamIdleTimeoutMs"),
|
|
3143
3290
|
t
|
|
@@ -3876,6 +4023,19 @@ window.__ModuleLoader__.load({
|
|
|
3876
4023
|
role: "status",
|
|
3877
4024
|
children: t("accountOpFailed")
|
|
3878
4025
|
}) : null,
|
|
4026
|
+
state.pendingCredentialCleanup.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4027
|
+
className: "cc-rowError",
|
|
4028
|
+
role: "status",
|
|
4029
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("accountCleanupPending") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4030
|
+
type: "button",
|
|
4031
|
+
className: "cc-btn cc-btnSm",
|
|
4032
|
+
disabled: disabled || state.accountBusy,
|
|
4033
|
+
onClick: () => {
|
|
4034
|
+
for (const ref of state.pendingCredentialCleanup) actions.cleanup(ref);
|
|
4035
|
+
},
|
|
4036
|
+
children: t("accountCleanupRetry")
|
|
4037
|
+
})]
|
|
4038
|
+
}) : null,
|
|
3879
4039
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3880
4040
|
className: "cc-accountList",
|
|
3881
4041
|
children: rows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountItem, {
|
|
@@ -4071,11 +4231,12 @@ window.__ModuleLoader__.load({
|
|
|
4071
4231
|
const disabled = !state.writable;
|
|
4072
4232
|
const savedVisible = useSavedFlash(state.savedCount);
|
|
4073
4233
|
const updateVersion = usePluginUpdate();
|
|
4074
|
-
const { createAccount, renameAccount, removeAccount, setAccountKey, clearAccountKey, setActiveAccount, setAccountModels, beginLogin, cancelLogin } = props;
|
|
4234
|
+
const { createAccount, renameAccount, removeAccount, retryCredentialCleanup, setAccountKey, clearAccountKey, setActiveAccount, setAccountModels, beginLogin, cancelLogin } = props;
|
|
4075
4235
|
const actions = (0, react.useMemo)(() => ({
|
|
4076
4236
|
create: createAccount,
|
|
4077
4237
|
rename: renameAccount,
|
|
4078
4238
|
remove: removeAccount,
|
|
4239
|
+
cleanup: retryCredentialCleanup,
|
|
4079
4240
|
setKey: setAccountKey,
|
|
4080
4241
|
clearKey: clearAccountKey,
|
|
4081
4242
|
setActive: setActiveAccount,
|
|
@@ -4086,6 +4247,7 @@ window.__ModuleLoader__.load({
|
|
|
4086
4247
|
createAccount,
|
|
4087
4248
|
renameAccount,
|
|
4088
4249
|
removeAccount,
|
|
4250
|
+
retryCredentialCleanup,
|
|
4089
4251
|
setAccountKey,
|
|
4090
4252
|
clearAccountKey,
|
|
4091
4253
|
setActiveAccount,
|
|
@@ -6362,7 +6524,7 @@ window.__ModuleLoader__.load({
|
|
|
6362
6524
|
.cc-usageHead{align-items:center;gap:8px;display:flex}
|
|
6363
6525
|
.cc-usageTitle{color:var(--dsw-alias-label-primary);flex:1;margin:0;font-size:14px;font-weight:500;line-height:22px}
|
|
6364
6526
|
.cc-usageAccount{max-width:40%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
|
|
6365
|
-
.cc-usagePlan{flex:none;white-space:nowrap;border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:999px;corner-shape:round;padding:0 7px;font-size:
|
|
6527
|
+
.cc-usagePlan{flex:none;white-space:nowrap;border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:999px;corner-shape:round;padding:0 7px;font-size:12px;font-weight:500;line-height:17px}
|
|
6366
6528
|
.cc-usagePlanStatus{flex:none;margin:0;white-space:nowrap;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}
|
|
6367
6529
|
.cc-usageHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}
|
|
6368
6530
|
/* Two fixed grids, not one auto-fit track: auto-fit wrapped the four activity
|
|
@@ -6494,8 +6656,8 @@ window.__ModuleLoader__.load({
|
|
|
6494
6656
|
bar into what is left beside them. Mirrors the dashboard's window block. */
|
|
6495
6657
|
.ccp-footRow{flex-direction:column;gap:4px;min-width:0;display:flex}
|
|
6496
6658
|
.ccp-footHead{align-items:baseline;gap:8px;min-width:0;display:flex}
|
|
6497
|
-
.ccp-footLabel{flex:1;color:var(--dsw-alias-label-tertiary);font-size:
|
|
6498
|
-
.ccp-footAmount{flex:none;color:var(--dsw-alias-label-secondary);font-size:
|
|
6659
|
+
.ccp-footLabel{flex:1;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}
|
|
6660
|
+
.ccp-footAmount{flex:none;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:16px;font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
6499
6661
|
/* The card's markup must stay PHRASING content — it renders inside the shell's
|
|
6500
6662
|
own button — so these bars are spans, which makes display:block load-bearing:
|
|
6501
6663
|
an inline box ignores width outright, so the fill would collapse to 0x0 and
|
|
@@ -6503,7 +6665,7 @@ window.__ModuleLoader__.load({
|
|
|
6503
6665
|
.ccp-footBar{display:block;background:var(--dsw-alias-bg-layer-2);border-radius:999px;height:5px;overflow:hidden}
|
|
6504
6666
|
.ccp-footFill{display:block;background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}
|
|
6505
6667
|
.ccp-footFillWarn{background:var(--dsw-alias-state-error-primary)}
|
|
6506
|
-
.ccp-footPct{flex:none;width:34px;color:var(--dsw-alias-label-secondary);text-align:right;font-size:
|
|
6668
|
+
.ccp-footPct{flex:none;width:34px;color:var(--dsw-alias-label-secondary);text-align:right;font-size:12px;line-height:16px;font-variant-numeric:tabular-nums}
|
|
6507
6669
|
|
|
6508
6670
|
/* The 56px rail: one icon button on the shell's own 36px rail cell, so the
|
|
6509
6671
|
collapsed column keeps a single 18px glyph like its siblings. */
|
|
@@ -6523,7 +6685,7 @@ window.__ModuleLoader__.load({
|
|
|
6523
6685
|
.ccp-title{margin:0;font-size:18px;font-weight:600;line-height:1.4}
|
|
6524
6686
|
.ccp-subtitle{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}
|
|
6525
6687
|
.ccp-spacer{flex:1}
|
|
6526
|
-
.ccp-meta{color:var(--dsw-alias-label-tertiary);font-size:
|
|
6688
|
+
.ccp-meta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;font-variant-numeric:tabular-nums}
|
|
6527
6689
|
/* The dashboard's exit: the primitive's own size="sm" geometry is kept; only the
|
|
6528
6690
|
glyph is enlarged and optically centred, so it reads as a dismiss control. */
|
|
6529
6691
|
.ccp-close{min-width:28px;justify-content:center;padding-left:0;padding-right:0}
|
|
@@ -6535,16 +6697,16 @@ window.__ModuleLoader__.load({
|
|
|
6535
6697
|
.ccp-noticeTitle{margin:0;font-size:13px;font-weight:600;line-height:1.5}
|
|
6536
6698
|
.ccp-noticeError .ccp-noticeTitle{color:var(--dsw-alias-state-error-primary)}
|
|
6537
6699
|
.ccp-noticeHint{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}
|
|
6538
|
-
.ccp-noticeDetail{margin:0;color:var(--dsw-alias-label-tertiary);font-size:
|
|
6700
|
+
.ccp-noticeDetail{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;word-break:break-word}
|
|
6539
6701
|
|
|
6540
6702
|
.ccp-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:14px;padding:16px 18px;flex-direction:column;gap:16px;display:flex}
|
|
6541
6703
|
.ccp-cardHead{align-items:center;gap:10px;display:flex;flex-wrap:wrap}
|
|
6542
6704
|
.ccp-avatar{flex:none;width:28px;height:28px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-module-platform);border-radius:50%;justify-content:center;align-items:center;font-size:12px;font-weight:600;line-height:1;display:inline-flex}
|
|
6543
6705
|
.ccp-cardIdentity{flex-direction:column;gap:1px;min-width:0;display:flex}
|
|
6544
6706
|
.ccp-cardTitle{font-size:13px;font-weight:600;line-height:1.4}
|
|
6545
|
-
.ccp-cardOwner{color:var(--dsw-alias-label-tertiary);font-size:
|
|
6707
|
+
.ccp-cardOwner{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:220px}
|
|
6546
6708
|
.ccp-block{flex-direction:column;gap:8px;display:flex}
|
|
6547
|
-
.ccp-blockTitle{margin:0;color:var(--dsw-alias-label-tertiary);font-size:
|
|
6709
|
+
.ccp-blockTitle{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:600;line-height:1.5;text-transform:uppercase;letter-spacing:.04em}
|
|
6548
6710
|
.ccp-planRow{align-items:center;gap:8px;display:flex;flex-wrap:wrap}
|
|
6549
6711
|
.ccp-fieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}
|
|
6550
6712
|
.ccp-planName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:1.5}
|
|
@@ -6552,9 +6714,9 @@ window.__ModuleLoader__.load({
|
|
|
6552
6714
|
/* The monthly credits and the usage totals share one grid. */
|
|
6553
6715
|
.ccp-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}
|
|
6554
6716
|
.ccp-tile{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:8px;padding:8px 10px;flex-direction:column;gap:2px;display:flex;min-width:0}
|
|
6555
|
-
.ccp-tileLabel{color:var(--dsw-alias-label-tertiary);font-size:
|
|
6717
|
+
.ccp-tileLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}
|
|
6556
6718
|
.ccp-tileValue{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4;font-variant-numeric:tabular-nums}
|
|
6557
|
-
.ccp-tileSub{color:var(--dsw-alias-label-tertiary);font-size:
|
|
6719
|
+
.ccp-tileSub{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
6558
6720
|
|
|
6559
6721
|
/* Quota bars: the monthly bar and the two windows. */
|
|
6560
6722
|
.ccp-windows{flex-direction:column;gap:14px;display:flex}
|
|
@@ -6563,16 +6725,16 @@ window.__ModuleLoader__.load({
|
|
|
6563
6725
|
.ccp-windowLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:1.5}
|
|
6564
6726
|
.ccp-windowValue{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
6565
6727
|
.ccp-windowPct{color:var(--dsw-alias-label-primary);min-width:38px;text-align:right;font-size:12px;font-weight:600;line-height:1.5;font-variant-numeric:tabular-nums}
|
|
6566
|
-
.ccp-warnTag{white-space:nowrap;background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary));border-radius:999px;padding:0 8px;font-size:
|
|
6728
|
+
.ccp-warnTag{white-space:nowrap;background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary));border-radius:999px;padding:0 8px;font-size:12px;font-weight:600;line-height:17px}
|
|
6567
6729
|
.ccp-bar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:8px}
|
|
6568
6730
|
.ccp-barFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}
|
|
6569
6731
|
.ccp-barFillWarn{background:var(--dsw-alias-state-error-primary)}
|
|
6570
|
-
.ccp-windowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:
|
|
6732
|
+
.ccp-windowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
6571
6733
|
|
|
6572
|
-
.ccp-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:
|
|
6734
|
+
.ccp-badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-brand-primary);border-radius:999px;padding:1px 8px;font-size:12px;font-weight:600;line-height:17px}
|
|
6573
6735
|
.ccp-badgeError{background:transparent;color:var(--dsw-alias-state-error-primary)}
|
|
6574
6736
|
.ccp-badgeWarn{background:var(--dsw-alias-state-warn-tertiary,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-warn-primary,var(--dsw-alias-label-secondary))}
|
|
6575
|
-
.ccp-badgeMuted{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:
|
|
6737
|
+
.ccp-badgeMuted{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:12px;font-weight:500;line-height:17px;max-width:220px;overflow:hidden;text-overflow:ellipsis}
|
|
6576
6738
|
|
|
6577
6739
|
/* Account switch: plain buttons, like the settings page's usage carousel. */
|
|
6578
6740
|
.ccp-tabs{flex-wrap:wrap;gap:6px;display:flex}
|
|
@@ -6626,7 +6788,7 @@ window.__ModuleLoader__.load({
|
|
|
6626
6788
|
modelAllowance: "${amount}/月",
|
|
6627
6789
|
modelAllowanceTitle: "该模型每月可用的额度(美元)。套餐内所有模型共用同一个月度额度池,这不是额外赠送的额度。",
|
|
6628
6790
|
visibleModelsTitle: "模型白名单",
|
|
6629
|
-
visibleModelsHint: "
|
|
6791
|
+
visibleModelsHint: "勾选要保留的模型,模型选择器就只列出这些;一个都不勾选时则显示全部模型。这里显示网页与终端合并后的有效选择;保存后两端一致,套餐权限仍独立过滤。",
|
|
6630
6792
|
visibleModelsPick: "选择要保留的模型…",
|
|
6631
6793
|
visibleModelsCount: "已选 {count} 个模型",
|
|
6632
6794
|
visibleModelsShowAll: "显示全部",
|
|
@@ -6635,8 +6797,11 @@ window.__ModuleLoader__.load({
|
|
|
6635
6797
|
overridden: "已覆盖",
|
|
6636
6798
|
reset: "重置",
|
|
6637
6799
|
invalidNumber: "无效数字",
|
|
6638
|
-
numberTooSmall: "
|
|
6639
|
-
numberTooLarge: "
|
|
6800
|
+
numberTooSmall: "重试次数不能小于 0",
|
|
6801
|
+
numberTooLarge: "重试次数不能大于 50",
|
|
6802
|
+
durationTooSmall: "不能小于 0.001 秒(1 毫秒)",
|
|
6803
|
+
durationTooLarge: "不能大于 3600 秒",
|
|
6804
|
+
durationInvalid: "请输入秒数,最多保留三位小数",
|
|
6640
6805
|
readOnly: "当前配置为只读。",
|
|
6641
6806
|
save: "保存",
|
|
6642
6807
|
saving: "保存中",
|
|
@@ -6730,6 +6895,8 @@ window.__ModuleLoader__.load({
|
|
|
6730
6895
|
accountNameN: "账户 {n}",
|
|
6731
6896
|
accountKeyPlaceholder: "粘贴 API 密钥",
|
|
6732
6897
|
accountOpFailed: "账户操作未能完成,请重试。",
|
|
6898
|
+
accountCleanupPending: "账户已移除,但有密钥尚未清理。可重试,不影响其他账户。",
|
|
6899
|
+
accountCleanupRetry: "重试清理密钥",
|
|
6733
6900
|
accountModels: "专用模型",
|
|
6734
6901
|
accountModelsHint: "选中的模型优先由此账户处理,此账户不可用时仍会自动切换。一个模型只属于一个账户,选中会把它从其他账户移过来。",
|
|
6735
6902
|
accountModelOwner: "属于 {name}",
|
|
@@ -6782,7 +6949,7 @@ window.__ModuleLoader__.load({
|
|
|
6782
6949
|
modelAllowance: "${amount}/mo",
|
|
6783
6950
|
modelAllowanceTitle: "Monthly usage this model can draw, in USD. Every model shares one monthly pool — this is not extra credit on top of the plan.",
|
|
6784
6951
|
visibleModelsTitle: "Model allowlist",
|
|
6785
|
-
visibleModelsHint: "Check the models you want to keep, and model pickers will list only those. If nothing is checked, every model is shown. After saving, the change applies
|
|
6952
|
+
visibleModelsHint: "Check the models you want to keep, and model pickers will list only those. If nothing is checked, every model is shown. After saving, the change applies in both web and terminal settings. This page shows their effective selection; plan access is filtered separately.",
|
|
6786
6953
|
visibleModelsPick: "Select models to keep…",
|
|
6787
6954
|
visibleModelsCount: "{count} model(s) selected",
|
|
6788
6955
|
visibleModelsShowAll: "Show all",
|
|
@@ -6791,8 +6958,11 @@ window.__ModuleLoader__.load({
|
|
|
6791
6958
|
overridden: "Overridden",
|
|
6792
6959
|
reset: "Reset",
|
|
6793
6960
|
invalidNumber: "Invalid number",
|
|
6794
|
-
numberTooSmall: "
|
|
6795
|
-
numberTooLarge: "
|
|
6961
|
+
numberTooSmall: "Retries must be at least 0",
|
|
6962
|
+
numberTooLarge: "Retries must not exceed 50",
|
|
6963
|
+
durationTooSmall: "Must be at least 0.001 seconds (1 ms)",
|
|
6964
|
+
durationTooLarge: "Must not exceed 3600 seconds",
|
|
6965
|
+
durationInvalid: "Enter seconds with at most three decimal places",
|
|
6796
6966
|
readOnly: "Settings are read-only.",
|
|
6797
6967
|
save: "Save",
|
|
6798
6968
|
saving: "Saving",
|
|
@@ -6886,6 +7056,8 @@ window.__ModuleLoader__.load({
|
|
|
6886
7056
|
accountNameN: "Account {n}",
|
|
6887
7057
|
accountKeyPlaceholder: "Paste an API key",
|
|
6888
7058
|
accountOpFailed: "The account change did not complete. Try again.",
|
|
7059
|
+
accountCleanupPending: "The account was removed, but credential cleanup is still pending. Retry without affecting other accounts.",
|
|
7060
|
+
accountCleanupRetry: "Retry credential cleanup",
|
|
6889
7061
|
accountModels: "Dedicated models",
|
|
6890
7062
|
accountModelsHint: "These models prefer this account and still switch when it is unavailable. A model belongs to one account; selecting it here moves it from any other.",
|
|
6891
7063
|
accountModelOwner: "on {name}",
|
|
@@ -7017,7 +7189,7 @@ window.__ModuleLoader__.load({
|
|
|
7017
7189
|
}, "dsh-commandcode-provider: usage namespace");
|
|
7018
7190
|
});
|
|
7019
7191
|
}, (error) => {
|
|
7020
|
-
usageMountError =
|
|
7192
|
+
usageMountError = readableErrorText(error);
|
|
7021
7193
|
});
|
|
7022
7194
|
return () => {
|
|
7023
7195
|
cancelled = true;
|
|
@@ -7130,7 +7302,11 @@ window.__ModuleLoader__.load({
|
|
|
7130
7302
|
return ref;
|
|
7131
7303
|
}),
|
|
7132
7304
|
renameAccount: (ref, label) => controller.renameAccount(ref, label),
|
|
7133
|
-
removeAccount: (ref) => controller.removeAccount(ref).then(
|
|
7305
|
+
removeAccount: (ref) => controller.removeAccount(ref).then((ok) => {
|
|
7306
|
+
if (ok || !controller.state().accounts.some((account) => account.ref === ref)) usageController.refresh();
|
|
7307
|
+
return ok;
|
|
7308
|
+
}),
|
|
7309
|
+
retryCredentialCleanup: (ref) => controller.retryCredentialCleanup(ref),
|
|
7134
7310
|
setAccountKey: (target, key) => controller.setAccountKey(target, key).then(refreshUsageOn),
|
|
7135
7311
|
clearAccountKey: (target) => controller.clearAccountKey(target).then(refreshUsageOn),
|
|
7136
7312
|
setActiveAccount: (id) => controller.setActiveAccount(id).then(refreshUsageOn),
|