@eddyskywalker/dsh-chatgpt-subscription 0.9.9 → 0.10.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/CHANGELOG.md +72 -0
- package/README.md +80 -2
- package/lib/client.js +1596 -207
- package/lib/client.js.map +1 -1
- package/lib/index.js +4834 -1019
- package/lib/types/client/ProviderHubSection.d.ts.map +1 -1
- package/lib/types/client/claude/locales.d.ts +2 -2
- package/lib/types/client/command-code/locales.d.ts +2 -2
- package/lib/types/client/index.d.ts +2 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/kimi-code/locales.d.ts +2 -2
- package/lib/types/client/minimax-code/MinimaxCodeComposerQuota.d.ts +27 -0
- package/lib/types/client/minimax-code/MinimaxCodeComposerQuota.d.ts.map +1 -0
- package/lib/types/client/minimax-code/MinimaxCodeSection.d.ts +49 -0
- package/lib/types/client/minimax-code/MinimaxCodeSection.d.ts.map +1 -0
- package/lib/types/client/minimax-code/api.d.ts +5 -0
- package/lib/types/client/minimax-code/api.d.ts.map +1 -0
- package/lib/types/client/minimax-code/locales.d.ts +341 -0
- package/lib/types/client/minimax-code/locales.d.ts.map +1 -0
- package/lib/types/client/minimax-code/styles.d.ts +12 -0
- package/lib/types/client/minimax-code/styles.d.ts.map +1 -0
- package/lib/types/client/styles.d.ts +19 -0
- package/lib/types/client/styles.d.ts.map +1 -1
- package/lib/types/compat.d.ts +1 -0
- package/lib/types/compat.d.ts.map +1 -1
- package/lib/types/host/agent-preset.d.ts.map +1 -1
- package/lib/types/host/claude/mapper.d.ts +11 -2
- package/lib/types/host/claude/mapper.d.ts.map +1 -1
- package/lib/types/host/minimax-code/account-pool.d.ts +219 -0
- package/lib/types/host/minimax-code/account-pool.d.ts.map +1 -0
- package/lib/types/host/minimax-code/adapter.d.ts +168 -0
- package/lib/types/host/minimax-code/adapter.d.ts.map +1 -0
- package/lib/types/host/minimax-code/client.d.ts +184 -0
- package/lib/types/host/minimax-code/client.d.ts.map +1 -0
- package/lib/types/host/minimax-code/mapper.d.ts +143 -0
- package/lib/types/host/minimax-code/mapper.d.ts.map +1 -0
- package/lib/types/host/minimax-code/model-catalog.d.ts +146 -0
- package/lib/types/host/minimax-code/model-catalog.d.ts.map +1 -0
- package/lib/types/host/minimax-code/oauth.d.ts +204 -0
- package/lib/types/host/minimax-code/oauth.d.ts.map +1 -0
- package/lib/types/host/minimax-code/routes.d.ts +79 -0
- package/lib/types/host/minimax-code/routes.d.ts.map +1 -0
- package/lib/types/host/minimax-code/token-store.d.ts +238 -0
- package/lib/types/host/minimax-code/token-store.d.ts.map +1 -0
- package/lib/types/host/minimax-code/types.d.ts +206 -0
- package/lib/types/host/minimax-code/types.d.ts.map +1 -0
- package/lib/types/host/subagent-model-authorization.d.ts +7 -0
- package/lib/types/host/subagent-model-authorization.d.ts.map +1 -1
- package/lib/types/index.d.ts +10 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/minimax-code-contracts.d.ts +166 -0
- package/lib/types/shared/minimax-code-contracts.d.ts.map +1 -0
- package/package.json +1 -1
- package/presets/dispatch/agent.cordis.yml +13 -1
package/lib/client.js
CHANGED
|
@@ -29,6 +29,34 @@ window.__ModuleLoader__.load({
|
|
|
29
29
|
let react = require("react");
|
|
30
30
|
react = __toESM(react, 1);
|
|
31
31
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
32
|
+
//#region src/shared/minimax-code-contracts.ts
|
|
33
|
+
const MINIMAX_CODE_PROVIDER_ID = "minimax-code";
|
|
34
|
+
const MINIMAX_CODE_PROVIDER_NAME = "MiniMax Code(编程订阅)";
|
|
35
|
+
/**
|
|
36
|
+
* 全线共用的思考档位,按从小到大的顺序排列。
|
|
37
|
+
*
|
|
38
|
+
* 设置卡片只渲染这一份列表:档位是线路级的词汇表(`isMinimaxCodeReasoningEffort`
|
|
39
|
+
* 就是按它校验的),而不是单个模型的能力表。某个模型实际接受哪些档位由
|
|
40
|
+
* `MinimaxCodeModelOption.reasoningEfforts` 单独给出——把两者合成一份会让卡片
|
|
41
|
+
* 在给一个只认 `default` 的模型显示 `max` 时无从判断是模型不支持还是文案没写。
|
|
42
|
+
*/
|
|
43
|
+
const MINIMAX_CODE_REASONING_EFFORTS = [
|
|
44
|
+
"default",
|
|
45
|
+
"low",
|
|
46
|
+
"medium",
|
|
47
|
+
"high",
|
|
48
|
+
"xhigh",
|
|
49
|
+
"max"
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* 路由前缀(host 暴露、client 消费)。
|
|
53
|
+
*
|
|
54
|
+
* 与其余各订阅线路一致:每条线路把自己的设置面挂在 `/<line>/api` 下
|
|
55
|
+
* (antigravity / claude / command-code / kimi-code / workbuddy 都是如此),
|
|
56
|
+
* 而不是挂到 Codex 那条线路的 `/api/dsh-chatgpt-subscription` 前缀下面。
|
|
57
|
+
* 唯一的 `/api/dsh-chatgpt-subscription` 前缀属于 Codex 自己的路由表。
|
|
58
|
+
*/
|
|
59
|
+
const MINIMAX_CODE_ROUTE_PREFIX = "/minimax-code/api";
|
|
32
60
|
const ROUTE_PREFIX = "/api/dsh-chatgpt-subscription";
|
|
33
61
|
const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
|
|
34
62
|
const CODEX_IMAGE_TOOL_NAME = "codex_image_generate";
|
|
@@ -56,7 +84,7 @@ window.__ModuleLoader__.load({
|
|
|
56
84
|
//#endregion
|
|
57
85
|
//#region src/client/CodexComposerQuota.tsx
|
|
58
86
|
function CodexComposerQuota({ api, directory, loadModelDirectory, t }) {
|
|
59
|
-
const modelState = useStore$
|
|
87
|
+
const modelState = useStore$6(directory);
|
|
60
88
|
const [status, setStatus] = (0, react.useState)(null);
|
|
61
89
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
62
90
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -103,7 +131,7 @@ window.__ModuleLoader__.load({
|
|
|
103
131
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quickQuotaLabel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota === null ? loading ? t("quickQuotaLoading") : "—" : formatPercent$1(quota.remainingPercent) })]
|
|
104
132
|
});
|
|
105
133
|
}
|
|
106
|
-
function useStore$
|
|
134
|
+
function useStore$6(store) {
|
|
107
135
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
108
136
|
}
|
|
109
137
|
function formatPercent$1(value) {
|
|
@@ -341,17 +369,17 @@ window.__ModuleLoader__.load({
|
|
|
341
369
|
//#region src/client/api.ts
|
|
342
370
|
var SubscriptionApi = class {
|
|
343
371
|
status() {
|
|
344
|
-
return request(`${ROUTE_PREFIX}/status`);
|
|
372
|
+
return request$1(`${ROUTE_PREFIX}/status`);
|
|
345
373
|
}
|
|
346
374
|
startLogin() {
|
|
347
|
-
return post(`${ROUTE_PREFIX}/login/start`, {});
|
|
375
|
+
return post$1(`${ROUTE_PREFIX}/login/start`, {});
|
|
348
376
|
}
|
|
349
377
|
cancelLogin(loginId) {
|
|
350
|
-
return post(`${ROUTE_PREFIX}/login/cancel`, { loginId });
|
|
378
|
+
return post$1(`${ROUTE_PREFIX}/login/cancel`, { loginId });
|
|
351
379
|
}
|
|
352
380
|
/** Sign out one pooled account; without an id, the active one. */
|
|
353
381
|
logout(accountId) {
|
|
354
|
-
return post(`${ROUTE_PREFIX}/logout`, accountId === void 0 ? {} : { accountId });
|
|
382
|
+
return post$1(`${ROUTE_PREFIX}/logout`, accountId === void 0 ? {} : { accountId });
|
|
355
383
|
}
|
|
356
384
|
/**
|
|
357
385
|
* One account-pool action, returning the refreshed status.
|
|
@@ -360,38 +388,38 @@ window.__ModuleLoader__.load({
|
|
|
360
388
|
* never has to guess what the pool looks like after a change.
|
|
361
389
|
*/
|
|
362
390
|
accountAction(action, body = {}) {
|
|
363
|
-
return post(`${ROUTE_PREFIX}/accounts`, {
|
|
391
|
+
return post$1(`${ROUTE_PREFIX}/accounts`, {
|
|
364
392
|
action,
|
|
365
393
|
...body
|
|
366
394
|
});
|
|
367
395
|
}
|
|
368
396
|
refresh() {
|
|
369
|
-
return post(`${ROUTE_PREFIX}/token/refresh`, {});
|
|
397
|
+
return post$1(`${ROUTE_PREFIX}/token/refresh`, {});
|
|
370
398
|
}
|
|
371
399
|
refreshQuota() {
|
|
372
|
-
return post(`${ROUTE_PREFIX}/quota/refresh`, {});
|
|
400
|
+
return post$1(`${ROUTE_PREFIX}/quota/refresh`, {});
|
|
373
401
|
}
|
|
374
402
|
useResetCredit() {
|
|
375
|
-
return post(`${ROUTE_PREFIX}/quota/reset-credit/use`, {});
|
|
403
|
+
return post$1(`${ROUTE_PREFIX}/quota/reset-credit/use`, {});
|
|
376
404
|
}
|
|
377
405
|
testConnection() {
|
|
378
|
-
return post(`${ROUTE_PREFIX}/connection/test`, {});
|
|
406
|
+
return post$1(`${ROUTE_PREFIX}/connection/test`, {});
|
|
379
407
|
}
|
|
380
408
|
updatePreferences(patch) {
|
|
381
|
-
return post(`${ROUTE_PREFIX}/preferences/update`, patch);
|
|
409
|
+
return post$1(`${ROUTE_PREFIX}/preferences/update`, patch);
|
|
382
410
|
}
|
|
383
411
|
events(loginId) {
|
|
384
412
|
return new EventSource(`${ROUTE_PREFIX}/login/events?loginId=${encodeURIComponent(loginId)}`);
|
|
385
413
|
}
|
|
386
414
|
};
|
|
387
|
-
async function post(url, body) {
|
|
388
|
-
return request(url, {
|
|
415
|
+
async function post$1(url, body) {
|
|
416
|
+
return request$1(url, {
|
|
389
417
|
method: "POST",
|
|
390
418
|
headers: { "content-type": "application/json" },
|
|
391
419
|
body: JSON.stringify(body)
|
|
392
420
|
});
|
|
393
421
|
}
|
|
394
|
-
async function request(url, init) {
|
|
422
|
+
async function request$1(url, init) {
|
|
395
423
|
const response = await fetch(url, {
|
|
396
424
|
...init,
|
|
397
425
|
credentials: "same-origin"
|
|
@@ -747,7 +775,7 @@ window.__ModuleLoader__.load({
|
|
|
747
775
|
load(true);
|
|
748
776
|
});
|
|
749
777
|
} catch (cause) {
|
|
750
|
-
if (!quiet) setError(messageOf(cause));
|
|
778
|
+
if (!quiet) setError(messageOf$1(cause));
|
|
751
779
|
}
|
|
752
780
|
}, []);
|
|
753
781
|
(0, react.useEffect)(() => {
|
|
@@ -808,7 +836,7 @@ window.__ModuleLoader__.load({
|
|
|
808
836
|
} catch (cause) {
|
|
809
837
|
popup?.close();
|
|
810
838
|
setBusy(null);
|
|
811
|
-
setError(messageOf(cause));
|
|
839
|
+
setError(messageOf$1(cause));
|
|
812
840
|
}
|
|
813
841
|
};
|
|
814
842
|
const cancelLogin = async () => {
|
|
@@ -822,7 +850,7 @@ window.__ModuleLoader__.load({
|
|
|
822
850
|
setAuthUrl(null);
|
|
823
851
|
await load();
|
|
824
852
|
} catch (cause) {
|
|
825
|
-
setError(messageOf(cause));
|
|
853
|
+
setError(messageOf$1(cause));
|
|
826
854
|
} finally {
|
|
827
855
|
setBusy(null);
|
|
828
856
|
}
|
|
@@ -899,7 +927,7 @@ window.__ModuleLoader__.load({
|
|
|
899
927
|
await updatePreferences({ contextWindowOverrides: { [model]: null } });
|
|
900
928
|
setContextDrafts((drafts) => ({
|
|
901
929
|
...drafts,
|
|
902
|
-
[model]: formatCapacity$
|
|
930
|
+
[model]: formatCapacity$6(resolveCodexCatalogEntry(model).contextWindow)
|
|
903
931
|
}));
|
|
904
932
|
};
|
|
905
933
|
/** Clear every stored override, including models the picker no longer shows. */
|
|
@@ -974,7 +1002,7 @@ window.__ModuleLoader__.load({
|
|
|
974
1002
|
const next = await apiRef.current.accountAction("relogin", { accountId });
|
|
975
1003
|
setStatus(next);
|
|
976
1004
|
} catch (cause) {
|
|
977
|
-
setError(messageOf(cause));
|
|
1005
|
+
setError(messageOf$1(cause));
|
|
978
1006
|
return;
|
|
979
1007
|
}
|
|
980
1008
|
await startLogin();
|
|
@@ -987,7 +1015,7 @@ window.__ModuleLoader__.load({
|
|
|
987
1015
|
try {
|
|
988
1016
|
await task();
|
|
989
1017
|
} catch (cause) {
|
|
990
|
-
setError(messageOf(cause));
|
|
1018
|
+
setError(messageOf$1(cause));
|
|
991
1019
|
} finally {
|
|
992
1020
|
setBusy(null);
|
|
993
1021
|
}
|
|
@@ -1035,7 +1063,7 @@ window.__ModuleLoader__.load({
|
|
|
1035
1063
|
onClearCooldown: (accountId) => void accountAction("clear-cooldown", accountId),
|
|
1036
1064
|
onRelogin: (accountId) => relogin(accountId),
|
|
1037
1065
|
onSetStrategy: (strategy) => void setRotationStrategy(strategy),
|
|
1038
|
-
storageValue: storageLabel(storage, t),
|
|
1066
|
+
storageValue: storageLabel$1(storage, t),
|
|
1039
1067
|
renderDetails: (entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [entry.planLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
1040
1068
|
t("plan"),
|
|
1041
1069
|
": ",
|
|
@@ -1113,7 +1141,7 @@ window.__ModuleLoader__.load({
|
|
|
1113
1141
|
}),
|
|
1114
1142
|
connection !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoRow, {
|
|
1115
1143
|
label: t("latency"),
|
|
1116
|
-
value: `${connection.latencyMs} ms · ${formatDate$
|
|
1144
|
+
value: `${connection.latencyMs} ms · ${formatDate$5(connection.checkedAt)}`
|
|
1117
1145
|
}) : null,
|
|
1118
1146
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1119
1147
|
className: "dsha-muted dsha-models-hint",
|
|
@@ -1393,7 +1421,7 @@ window.__ModuleLoader__.load({
|
|
|
1393
1421
|
id: inputId,
|
|
1394
1422
|
type: "text",
|
|
1395
1423
|
inputMode: "numeric",
|
|
1396
|
-
value: draft ?? formatCapacity$
|
|
1424
|
+
value: draft ?? formatCapacity$6(fallback),
|
|
1397
1425
|
disabled: busy !== null,
|
|
1398
1426
|
"aria-label": entry.name + " " + t("contextWindow"),
|
|
1399
1427
|
onChange: (event) => {
|
|
@@ -1525,7 +1553,7 @@ window.__ModuleLoader__.load({
|
|
|
1525
1553
|
children: [
|
|
1526
1554
|
t("updated"),
|
|
1527
1555
|
": ",
|
|
1528
|
-
formatDate$
|
|
1556
|
+
formatDate$5(quota.fetchedAt)
|
|
1529
1557
|
]
|
|
1530
1558
|
}) : null
|
|
1531
1559
|
]
|
|
@@ -1569,7 +1597,7 @@ window.__ModuleLoader__.load({
|
|
|
1569
1597
|
})]
|
|
1570
1598
|
});
|
|
1571
1599
|
}
|
|
1572
|
-
function storageLabel(storage, t) {
|
|
1600
|
+
function storageLabel$1(storage, t) {
|
|
1573
1601
|
if (storage === void 0 || !storage.available) return t("storageUnavailable");
|
|
1574
1602
|
if (storage.kind === "windows-dpapi") return t("storageWindows");
|
|
1575
1603
|
if (storage.kind === "macos-keychain") return t("storageMacKeychain");
|
|
@@ -1676,7 +1704,7 @@ window.__ModuleLoader__.load({
|
|
|
1676
1704
|
return `${value} ${t("limitWindow")}`;
|
|
1677
1705
|
}
|
|
1678
1706
|
}
|
|
1679
|
-
function parsePositiveCapacity$
|
|
1707
|
+
function parsePositiveCapacity$6(value) {
|
|
1680
1708
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
1681
1709
|
if (matched === null) return null;
|
|
1682
1710
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
@@ -1684,10 +1712,10 @@ window.__ModuleLoader__.load({
|
|
|
1684
1712
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
1685
1713
|
}
|
|
1686
1714
|
function parseCapacity(value, maxContextWindow = GPT_56_MAX_CONTEXT_WINDOW) {
|
|
1687
|
-
const parsed = parsePositiveCapacity$
|
|
1715
|
+
const parsed = parsePositiveCapacity$6(value);
|
|
1688
1716
|
return parsed !== null && parsed <= maxContextWindow ? parsed : null;
|
|
1689
1717
|
}
|
|
1690
|
-
function formatCapacity$
|
|
1718
|
+
function formatCapacity$6(value) {
|
|
1691
1719
|
if (value % 1e3 === 0) return `${value / 1e3}K`;
|
|
1692
1720
|
return String(value);
|
|
1693
1721
|
}
|
|
@@ -1708,7 +1736,7 @@ window.__ModuleLoader__.load({
|
|
|
1708
1736
|
].filter((part) => part !== null);
|
|
1709
1737
|
return parts.length > 0 ? parts.join(" · ") : t("unknown");
|
|
1710
1738
|
}
|
|
1711
|
-
function formatDate$
|
|
1739
|
+
function formatDate$5(seconds) {
|
|
1712
1740
|
if (seconds === void 0 || seconds === null || typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) return "—";
|
|
1713
1741
|
const ms = seconds > 1e10 ? seconds : seconds * 1e3;
|
|
1714
1742
|
try {
|
|
@@ -1723,7 +1751,7 @@ window.__ModuleLoader__.load({
|
|
|
1723
1751
|
function formatReset$4(seconds) {
|
|
1724
1752
|
if (seconds === void 0 || seconds === null || typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) return "—";
|
|
1725
1753
|
const ms = seconds > 1e10 ? seconds : seconds * 1e3;
|
|
1726
|
-
const absolute = formatDate$
|
|
1754
|
+
const absolute = formatDate$5(seconds);
|
|
1727
1755
|
const diff = ms - Date.now();
|
|
1728
1756
|
const abs = Math.abs(diff);
|
|
1729
1757
|
const [amount, unit] = abs >= 864e5 ? [Math.round(diff / 864e5), "day"] : abs >= 36e5 ? [Math.round(diff / 36e5), "hour"] : [Math.round(diff / 6e4), "minute"];
|
|
@@ -1733,13 +1761,13 @@ window.__ModuleLoader__.load({
|
|
|
1733
1761
|
return absolute;
|
|
1734
1762
|
}
|
|
1735
1763
|
}
|
|
1736
|
-
function messageOf(error) {
|
|
1764
|
+
function messageOf$1(error) {
|
|
1737
1765
|
return error instanceof Error ? error.message : String(error);
|
|
1738
1766
|
}
|
|
1739
1767
|
//#endregion
|
|
1740
1768
|
//#region src/client/antigravity/locales.ts
|
|
1741
1769
|
const NS_ANTIGRAVITY = "dsh-antigravity";
|
|
1742
|
-
const zh$
|
|
1770
|
+
const zh$6 = {
|
|
1743
1771
|
...accountPoolZh,
|
|
1744
1772
|
title: "Antigravity",
|
|
1745
1773
|
pageDesc: "登录 Google Antigravity / Cloud Code Assist,并查看当前账号的共享额度。",
|
|
@@ -1809,7 +1837,7 @@ window.__ModuleLoader__.load({
|
|
|
1809
1837
|
loginFailed: "登录失败",
|
|
1810
1838
|
tokens: "tokens"
|
|
1811
1839
|
};
|
|
1812
|
-
const en$
|
|
1840
|
+
const en$6 = {
|
|
1813
1841
|
...accountPoolEn,
|
|
1814
1842
|
title: "Antigravity",
|
|
1815
1843
|
pageDesc: "Sign in to Google Antigravity / Cloud Code Assist and view shared quotas.",
|
|
@@ -1879,11 +1907,11 @@ window.__ModuleLoader__.load({
|
|
|
1879
1907
|
loginFailed: "Login failed",
|
|
1880
1908
|
tokens: "tokens"
|
|
1881
1909
|
};
|
|
1882
|
-
const dictionaries$
|
|
1883
|
-
zh: zh$
|
|
1884
|
-
"zh-CN": zh$
|
|
1885
|
-
en: en$
|
|
1886
|
-
"en-US": en$
|
|
1910
|
+
const dictionaries$6 = {
|
|
1911
|
+
zh: zh$6,
|
|
1912
|
+
"zh-CN": zh$6,
|
|
1913
|
+
en: en$6,
|
|
1914
|
+
"en-US": en$6
|
|
1887
1915
|
};
|
|
1888
1916
|
//#endregion
|
|
1889
1917
|
//#region src/client/antigravity/AntigravitySection.tsx
|
|
@@ -1900,14 +1928,14 @@ window.__ModuleLoader__.load({
|
|
|
1900
1928
|
if (!res.ok || !json.ok) throw new Error(json.error || `HTTP ${res.status}`);
|
|
1901
1929
|
return json.value;
|
|
1902
1930
|
}
|
|
1903
|
-
function parsePositiveCapacity$
|
|
1931
|
+
function parsePositiveCapacity$5(value) {
|
|
1904
1932
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
1905
1933
|
if (matched === null) return null;
|
|
1906
1934
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
1907
1935
|
const parsed = Number(matched[1]) * multiplier;
|
|
1908
1936
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
1909
1937
|
}
|
|
1910
|
-
function formatCapacity$
|
|
1938
|
+
function formatCapacity$5(value) {
|
|
1911
1939
|
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
1912
1940
|
if (value % 1e3 === 0) return `${value / 1e3}K`;
|
|
1913
1941
|
return String(value);
|
|
@@ -1917,9 +1945,9 @@ window.__ModuleLoader__.load({
|
|
|
1917
1945
|
* toggle: a model that was just enabled has no draft yet, and the context
|
|
1918
1946
|
* window section only renders enabled models.
|
|
1919
1947
|
*/
|
|
1920
|
-
function contextDraftsFor$
|
|
1948
|
+
function contextDraftsFor$5(status) {
|
|
1921
1949
|
const drafts = {};
|
|
1922
|
-
for (const model of status.models) drafts[model.id] = formatCapacity$
|
|
1950
|
+
for (const model of status.models) drafts[model.id] = formatCapacity$5(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
1923
1951
|
return drafts;
|
|
1924
1952
|
}
|
|
1925
1953
|
function formatResetTime(resetTime) {
|
|
@@ -1933,7 +1961,7 @@ window.__ModuleLoader__.load({
|
|
|
1933
1961
|
if (hours > 0) return `${hours}h ${mins % 60}m`;
|
|
1934
1962
|
return `${mins}m`;
|
|
1935
1963
|
}
|
|
1936
|
-
function formatDate$
|
|
1964
|
+
function formatDate$4(ms) {
|
|
1937
1965
|
if (!ms || ms <= 0) return "—";
|
|
1938
1966
|
try {
|
|
1939
1967
|
return new Intl.DateTimeFormat(void 0, {
|
|
@@ -1955,7 +1983,7 @@ window.__ModuleLoader__.load({
|
|
|
1955
1983
|
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
1956
1984
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
1957
1985
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
1958
|
-
const t = zh$
|
|
1986
|
+
const t = zh$6;
|
|
1959
1987
|
const notifyChange = (0, react.useCallback)(() => {
|
|
1960
1988
|
onModelChange?.();
|
|
1961
1989
|
loadModelDirectory?.();
|
|
@@ -1968,7 +1996,7 @@ window.__ModuleLoader__.load({
|
|
|
1968
1996
|
try {
|
|
1969
1997
|
const data = await fetchApi$9("/status");
|
|
1970
1998
|
setStatus(data);
|
|
1971
|
-
setContextDrafts(contextDraftsFor$
|
|
1999
|
+
setContextDrafts(contextDraftsFor$5(data));
|
|
1972
2000
|
quotaFollowUp.current ??= createQuotaFollowUp();
|
|
1973
2001
|
quotaFollowUp.current.observe(data.quotaRefreshing === true, () => {
|
|
1974
2002
|
loadStatus(true);
|
|
@@ -2143,7 +2171,7 @@ window.__ModuleLoader__.load({
|
|
|
2143
2171
|
body: JSON.stringify({ enabledModelIds: nextEnabled })
|
|
2144
2172
|
});
|
|
2145
2173
|
setStatus(updated);
|
|
2146
|
-
setContextDrafts(contextDraftsFor$
|
|
2174
|
+
setContextDrafts(contextDraftsFor$5(updated));
|
|
2147
2175
|
notifyChange();
|
|
2148
2176
|
} catch (err) {
|
|
2149
2177
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -2158,7 +2186,7 @@ window.__ModuleLoader__.load({
|
|
|
2158
2186
|
body: JSON.stringify({ enabledModelIds: nextEnabled })
|
|
2159
2187
|
});
|
|
2160
2188
|
setStatus(updated);
|
|
2161
|
-
setContextDrafts(contextDraftsFor$
|
|
2189
|
+
setContextDrafts(contextDraftsFor$5(updated));
|
|
2162
2190
|
notifyChange();
|
|
2163
2191
|
} catch (err) {
|
|
2164
2192
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -2178,7 +2206,7 @@ window.__ModuleLoader__.load({
|
|
|
2178
2206
|
};
|
|
2179
2207
|
const handleSaveContextWindow = async (modelId) => {
|
|
2180
2208
|
const raw = contextDrafts[modelId] || "";
|
|
2181
|
-
const parsed = parsePositiveCapacity$
|
|
2209
|
+
const parsed = parsePositiveCapacity$5(raw);
|
|
2182
2210
|
if (parsed === null) {
|
|
2183
2211
|
setError(`无效的上下文容量值: ${raw}`);
|
|
2184
2212
|
return;
|
|
@@ -2193,7 +2221,7 @@ window.__ModuleLoader__.load({
|
|
|
2193
2221
|
setStatus(updated);
|
|
2194
2222
|
setContextDrafts((prev) => ({
|
|
2195
2223
|
...prev,
|
|
2196
|
-
[modelId]: formatCapacity$
|
|
2224
|
+
[modelId]: formatCapacity$5(parsed)
|
|
2197
2225
|
}));
|
|
2198
2226
|
notifyChange();
|
|
2199
2227
|
} catch (err) {
|
|
@@ -2216,7 +2244,7 @@ window.__ModuleLoader__.load({
|
|
|
2216
2244
|
const model = updated.models.find((candidate) => candidate.id === modelId);
|
|
2217
2245
|
return model === void 0 ? prev : {
|
|
2218
2246
|
...prev,
|
|
2219
|
-
[modelId]: formatCapacity$
|
|
2247
|
+
[modelId]: formatCapacity$5(model.defaultContextWindow)
|
|
2220
2248
|
};
|
|
2221
2249
|
});
|
|
2222
2250
|
notifyChange();
|
|
@@ -2239,7 +2267,7 @@ window.__ModuleLoader__.load({
|
|
|
2239
2267
|
body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
|
|
2240
2268
|
});
|
|
2241
2269
|
setStatus(updated);
|
|
2242
|
-
setContextDrafts(contextDraftsFor$
|
|
2270
|
+
setContextDrafts(contextDraftsFor$5(updated));
|
|
2243
2271
|
notifyChange();
|
|
2244
2272
|
} catch (err) {
|
|
2245
2273
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -2288,12 +2316,12 @@ window.__ModuleLoader__.load({
|
|
|
2288
2316
|
account.expiresAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2289
2317
|
t.expires,
|
|
2290
2318
|
": ",
|
|
2291
|
-
formatDate$
|
|
2319
|
+
formatDate$4(account.expiresAt)
|
|
2292
2320
|
] }),
|
|
2293
2321
|
account.lastUsedAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2294
2322
|
t.lastUsed,
|
|
2295
2323
|
": ",
|
|
2296
|
-
formatDate$
|
|
2324
|
+
formatDate$4(account.lastUsedAt)
|
|
2297
2325
|
] })
|
|
2298
2326
|
] })
|
|
2299
2327
|
}),
|
|
@@ -2572,7 +2600,7 @@ window.__ModuleLoader__.load({
|
|
|
2572
2600
|
//#endregion
|
|
2573
2601
|
//#region src/client/command-code/locales.ts
|
|
2574
2602
|
const NS_COMMAND_CODE = "dsh-command-code";
|
|
2575
|
-
const zh$
|
|
2603
|
+
const zh$5 = {
|
|
2576
2604
|
...accountPoolZh,
|
|
2577
2605
|
title: "Command Code",
|
|
2578
2606
|
pageDesc: "登录 Command Code,管理可用模型、上下文窗口与额度。",
|
|
@@ -2644,7 +2672,7 @@ window.__ModuleLoader__.load({
|
|
|
2644
2672
|
loginFailed: "登录失败",
|
|
2645
2673
|
tokens: "tokens"
|
|
2646
2674
|
};
|
|
2647
|
-
const en$
|
|
2675
|
+
const en$5 = {
|
|
2648
2676
|
...accountPoolEn,
|
|
2649
2677
|
title: "Command Code",
|
|
2650
2678
|
pageDesc: "Sign in to Command Code and manage models, context windows, and quota.",
|
|
@@ -2716,11 +2744,11 @@ window.__ModuleLoader__.load({
|
|
|
2716
2744
|
loginFailed: "Sign-in failed",
|
|
2717
2745
|
tokens: "tokens"
|
|
2718
2746
|
};
|
|
2719
|
-
const dictionaries$
|
|
2720
|
-
zh: zh$
|
|
2721
|
-
"zh-CN": zh$
|
|
2722
|
-
en: en$
|
|
2723
|
-
"en-US": en$
|
|
2747
|
+
const dictionaries$5 = {
|
|
2748
|
+
zh: zh$5,
|
|
2749
|
+
"zh-CN": zh$5,
|
|
2750
|
+
en: en$5,
|
|
2751
|
+
"en-US": en$5
|
|
2724
2752
|
};
|
|
2725
2753
|
//#endregion
|
|
2726
2754
|
//#region src/client/command-code/CommandCodeSection.tsx
|
|
@@ -2750,14 +2778,14 @@ window.__ModuleLoader__.load({
|
|
|
2750
2778
|
return json.value;
|
|
2751
2779
|
}
|
|
2752
2780
|
/** Parse "1M", "512K", "200000" into a positive integer token count. */
|
|
2753
|
-
function parsePositiveCapacity$
|
|
2781
|
+
function parsePositiveCapacity$4(value) {
|
|
2754
2782
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
2755
2783
|
if (matched === null) return null;
|
|
2756
2784
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
2757
2785
|
const parsed = Number(matched[1]) * multiplier;
|
|
2758
2786
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
2759
2787
|
}
|
|
2760
|
-
function formatCapacity$
|
|
2788
|
+
function formatCapacity$4(value) {
|
|
2761
2789
|
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
2762
2790
|
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
2763
2791
|
return String(value);
|
|
@@ -2767,9 +2795,9 @@ window.__ModuleLoader__.load({
|
|
|
2767
2795
|
* toggle: a model that was just enabled has no draft yet, and the context
|
|
2768
2796
|
* window section only renders enabled models.
|
|
2769
2797
|
*/
|
|
2770
|
-
function contextDraftsFor$
|
|
2798
|
+
function contextDraftsFor$4(status) {
|
|
2771
2799
|
const drafts = {};
|
|
2772
|
-
for (const model of status.models) drafts[model.id] = formatCapacity$
|
|
2800
|
+
for (const model of status.models) drafts[model.id] = formatCapacity$4(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
2773
2801
|
return drafts;
|
|
2774
2802
|
}
|
|
2775
2803
|
function formatReset$3(resetsAt) {
|
|
@@ -2794,7 +2822,7 @@ window.__ModuleLoader__.load({
|
|
|
2794
2822
|
const [apiKey, setApiKey] = (0, react.useState)("");
|
|
2795
2823
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
2796
2824
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
2797
|
-
const t = zh$
|
|
2825
|
+
const t = zh$5;
|
|
2798
2826
|
const notifyChange = (0, react.useCallback)(() => {
|
|
2799
2827
|
onModelChange?.();
|
|
2800
2828
|
loadModelDirectory?.();
|
|
@@ -2804,7 +2832,7 @@ window.__ModuleLoader__.load({
|
|
|
2804
2832
|
try {
|
|
2805
2833
|
const data = await fetchApi$8("/status");
|
|
2806
2834
|
setStatus(data);
|
|
2807
|
-
setContextDrafts(contextDraftsFor$
|
|
2835
|
+
setContextDrafts(contextDraftsFor$4(data));
|
|
2808
2836
|
quotaFollowUp.current ??= createQuotaFollowUp();
|
|
2809
2837
|
quotaFollowUp.current.observe(data.quotaRefreshing === true, () => {
|
|
2810
2838
|
loadStatus(true);
|
|
@@ -2963,7 +2991,7 @@ window.__ModuleLoader__.load({
|
|
|
2963
2991
|
setError(null);
|
|
2964
2992
|
const updated = await fetchApi$8("/catalog/refresh", { method: "POST" });
|
|
2965
2993
|
setStatus(updated);
|
|
2966
|
-
setContextDrafts(contextDraftsFor$
|
|
2994
|
+
setContextDrafts(contextDraftsFor$4(updated));
|
|
2967
2995
|
notifyChange();
|
|
2968
2996
|
} catch (err) {
|
|
2969
2997
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -2990,7 +3018,7 @@ window.__ModuleLoader__.load({
|
|
|
2990
3018
|
body: JSON.stringify({ enabledModelIds })
|
|
2991
3019
|
});
|
|
2992
3020
|
setStatus(updated);
|
|
2993
|
-
setContextDrafts(contextDraftsFor$
|
|
3021
|
+
setContextDrafts(contextDraftsFor$4(updated));
|
|
2994
3022
|
notifyChange();
|
|
2995
3023
|
} catch (err) {
|
|
2996
3024
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -3037,7 +3065,7 @@ window.__ModuleLoader__.load({
|
|
|
3037
3065
|
};
|
|
3038
3066
|
const handleSaveContextWindow = async (modelId) => {
|
|
3039
3067
|
const raw = contextDrafts[modelId] || "";
|
|
3040
|
-
const parsed = parsePositiveCapacity$
|
|
3068
|
+
const parsed = parsePositiveCapacity$4(raw);
|
|
3041
3069
|
if (parsed === null) {
|
|
3042
3070
|
setError(`Invalid context capacity: ${raw}`);
|
|
3043
3071
|
return;
|
|
@@ -3052,7 +3080,7 @@ window.__ModuleLoader__.load({
|
|
|
3052
3080
|
setStatus(updated);
|
|
3053
3081
|
setContextDrafts((prev) => ({
|
|
3054
3082
|
...prev,
|
|
3055
|
-
[modelId]: formatCapacity$
|
|
3083
|
+
[modelId]: formatCapacity$4(parsed)
|
|
3056
3084
|
}));
|
|
3057
3085
|
notifyChange();
|
|
3058
3086
|
} catch (err) {
|
|
@@ -3075,7 +3103,7 @@ window.__ModuleLoader__.load({
|
|
|
3075
3103
|
const model = updated.models.find((candidate) => candidate.id === modelId);
|
|
3076
3104
|
return model === void 0 ? prev : {
|
|
3077
3105
|
...prev,
|
|
3078
|
-
[modelId]: formatCapacity$
|
|
3106
|
+
[modelId]: formatCapacity$4(model.defaultContextWindow)
|
|
3079
3107
|
};
|
|
3080
3108
|
});
|
|
3081
3109
|
notifyChange();
|
|
@@ -3098,7 +3126,7 @@ window.__ModuleLoader__.load({
|
|
|
3098
3126
|
body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
|
|
3099
3127
|
});
|
|
3100
3128
|
setStatus(updated);
|
|
3101
|
-
setContextDrafts(contextDraftsFor$
|
|
3129
|
+
setContextDrafts(contextDraftsFor$4(updated));
|
|
3102
3130
|
notifyChange();
|
|
3103
3131
|
} catch (err) {
|
|
3104
3132
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -3502,7 +3530,7 @@ window.__ModuleLoader__.load({
|
|
|
3502
3530
|
* provider — the same reason every sibling line has one.
|
|
3503
3531
|
*/
|
|
3504
3532
|
const NS_CLAUDE = "dsh-claude";
|
|
3505
|
-
const zh$
|
|
3533
|
+
const zh$4 = {
|
|
3506
3534
|
...accountPoolZh,
|
|
3507
3535
|
title: "Claude(订阅)",
|
|
3508
3536
|
pageDesc: "登录 Claude Pro/Max 订阅,管理模型、思考档位、上下文窗口与额度。",
|
|
@@ -3626,7 +3654,7 @@ window.__ModuleLoader__.load({
|
|
|
3626
3654
|
copy: "复制",
|
|
3627
3655
|
copied: "已复制"
|
|
3628
3656
|
};
|
|
3629
|
-
const en$
|
|
3657
|
+
const en$4 = {
|
|
3630
3658
|
...accountPoolEn,
|
|
3631
3659
|
title: "Claude (subscription)",
|
|
3632
3660
|
pageDesc: "Sign in to a Claude Pro/Max subscription and manage models, thinking levels, context windows and quota.",
|
|
@@ -3750,11 +3778,11 @@ window.__ModuleLoader__.load({
|
|
|
3750
3778
|
copy: "Copy",
|
|
3751
3779
|
copied: "Copied"
|
|
3752
3780
|
};
|
|
3753
|
-
const dictionaries$
|
|
3754
|
-
zh: zh$
|
|
3755
|
-
"zh-CN": zh$
|
|
3756
|
-
en: en$
|
|
3757
|
-
"en-US": en$
|
|
3781
|
+
const dictionaries$4 = {
|
|
3782
|
+
zh: zh$4,
|
|
3783
|
+
"zh-CN": zh$4,
|
|
3784
|
+
en: en$4,
|
|
3785
|
+
"en-US": en$4
|
|
3758
3786
|
};
|
|
3759
3787
|
//#endregion
|
|
3760
3788
|
//#region src/client/claude/ClaudeSection.tsx
|
|
@@ -3780,14 +3808,14 @@ window.__ModuleLoader__.load({
|
|
|
3780
3808
|
return json.value;
|
|
3781
3809
|
}
|
|
3782
3810
|
/** Parse "1M", "512K", "200000" into a positive integer token count. */
|
|
3783
|
-
function parsePositiveCapacity$
|
|
3811
|
+
function parsePositiveCapacity$3(value) {
|
|
3784
3812
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
3785
3813
|
if (matched === null) return null;
|
|
3786
3814
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
3787
3815
|
const parsed = Number(matched[1]) * multiplier;
|
|
3788
3816
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
3789
3817
|
}
|
|
3790
|
-
function formatCapacity$
|
|
3818
|
+
function formatCapacity$3(value) {
|
|
3791
3819
|
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
3792
3820
|
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
3793
3821
|
return String(value);
|
|
@@ -3799,12 +3827,12 @@ window.__ModuleLoader__.load({
|
|
|
3799
3827
|
* and the context window section only renders enabled models — exactly the rule
|
|
3800
3828
|
* the sibling lines state in the same place.
|
|
3801
3829
|
*/
|
|
3802
|
-
function contextDraftsFor$
|
|
3830
|
+
function contextDraftsFor$3(status) {
|
|
3803
3831
|
const drafts = {};
|
|
3804
|
-
for (const model of status.models) drafts[model.id] = formatCapacity$
|
|
3832
|
+
for (const model of status.models) drafts[model.id] = formatCapacity$3(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
3805
3833
|
return drafts;
|
|
3806
3834
|
}
|
|
3807
|
-
function formatDate$
|
|
3835
|
+
function formatDate$3(ms) {
|
|
3808
3836
|
if (ms === void 0 || ms === null || ms <= 0) return "—";
|
|
3809
3837
|
try {
|
|
3810
3838
|
return new Intl.DateTimeFormat(void 0, {
|
|
@@ -3844,11 +3872,11 @@ window.__ModuleLoader__.load({
|
|
|
3844
3872
|
* out here would hide a choice the host would accept and a catalog may expose.
|
|
3845
3873
|
*/
|
|
3846
3874
|
const EFFORT_LABELS$1 = {
|
|
3847
|
-
low: zh$
|
|
3848
|
-
medium: zh$
|
|
3849
|
-
high: zh$
|
|
3850
|
-
xhigh: zh$
|
|
3851
|
-
max: zh$
|
|
3875
|
+
low: zh$4.effortLow,
|
|
3876
|
+
medium: zh$4.effortMedium,
|
|
3877
|
+
high: zh$4.effortHigh,
|
|
3878
|
+
xhigh: zh$4.effortXHigh,
|
|
3879
|
+
max: zh$4.effortMax
|
|
3852
3880
|
};
|
|
3853
3881
|
/** One-line capability summary shown as a model pill's hover title. */
|
|
3854
3882
|
function modelFacts(model, t) {
|
|
@@ -3873,7 +3901,7 @@ window.__ModuleLoader__.load({
|
|
|
3873
3901
|
const [connection, setConnection] = (0, react.useState)(null);
|
|
3874
3902
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
3875
3903
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
3876
|
-
const t = zh$
|
|
3904
|
+
const t = zh$4;
|
|
3877
3905
|
const notifyChange = (0, react.useCallback)(() => {
|
|
3878
3906
|
onModelChange?.();
|
|
3879
3907
|
loadModelDirectory?.();
|
|
@@ -3887,7 +3915,7 @@ window.__ModuleLoader__.load({
|
|
|
3887
3915
|
try {
|
|
3888
3916
|
const data = await fetchApi$7("/status");
|
|
3889
3917
|
setStatus(data);
|
|
3890
|
-
setContextDrafts(contextDraftsFor$
|
|
3918
|
+
setContextDrafts(contextDraftsFor$3(data));
|
|
3891
3919
|
quotaFollowUp.current ??= createQuotaFollowUp();
|
|
3892
3920
|
quotaFollowUp.current.observe(data.quotaRefreshing === true, () => {
|
|
3893
3921
|
loadStatus(true);
|
|
@@ -3969,7 +3997,7 @@ window.__ModuleLoader__.load({
|
|
|
3969
3997
|
body: JSON.stringify({ input: pasteValue })
|
|
3970
3998
|
});
|
|
3971
3999
|
setStatus(updated);
|
|
3972
|
-
setContextDrafts(contextDraftsFor$
|
|
4000
|
+
setContextDrafts(contextDraftsFor$3(updated));
|
|
3973
4001
|
setFlow({ status: "idle" });
|
|
3974
4002
|
setPasteValue("");
|
|
3975
4003
|
notifyChange();
|
|
@@ -3990,7 +4018,7 @@ window.__ModuleLoader__.load({
|
|
|
3990
4018
|
setError(null);
|
|
3991
4019
|
const updated = await fetchApi$7("/adopt", { method: "POST" });
|
|
3992
4020
|
setStatus(updated);
|
|
3993
|
-
setContextDrafts(contextDraftsFor$
|
|
4021
|
+
setContextDrafts(contextDraftsFor$3(updated));
|
|
3994
4022
|
notifyChange();
|
|
3995
4023
|
} catch (err) {
|
|
3996
4024
|
reportError(err);
|
|
@@ -4098,7 +4126,7 @@ window.__ModuleLoader__.load({
|
|
|
4098
4126
|
setError(null);
|
|
4099
4127
|
const updated = await fetchApi$7("/catalog/refresh", { method: "POST" });
|
|
4100
4128
|
setStatus(updated);
|
|
4101
|
-
setContextDrafts(contextDraftsFor$
|
|
4129
|
+
setContextDrafts(contextDraftsFor$3(updated));
|
|
4102
4130
|
notifyChange();
|
|
4103
4131
|
} catch (err) {
|
|
4104
4132
|
reportError(err);
|
|
@@ -4127,7 +4155,7 @@ window.__ModuleLoader__.load({
|
|
|
4127
4155
|
body: JSON.stringify({ enabledModelIds })
|
|
4128
4156
|
});
|
|
4129
4157
|
setStatus(updated);
|
|
4130
|
-
setContextDrafts(contextDraftsFor$
|
|
4158
|
+
setContextDrafts(contextDraftsFor$3(updated));
|
|
4131
4159
|
notifyChange();
|
|
4132
4160
|
} catch (err) {
|
|
4133
4161
|
reportError(err);
|
|
@@ -4174,7 +4202,7 @@ window.__ModuleLoader__.load({
|
|
|
4174
4202
|
};
|
|
4175
4203
|
const handleSaveContextWindow = async (modelId) => {
|
|
4176
4204
|
const raw = contextDrafts[modelId] || "";
|
|
4177
|
-
const parsed = parsePositiveCapacity$
|
|
4205
|
+
const parsed = parsePositiveCapacity$3(raw);
|
|
4178
4206
|
if (parsed === null) {
|
|
4179
4207
|
setError(t.contextWindowInvalid.replace("{value}", raw));
|
|
4180
4208
|
return;
|
|
@@ -4189,7 +4217,7 @@ window.__ModuleLoader__.load({
|
|
|
4189
4217
|
setStatus(updated);
|
|
4190
4218
|
setContextDrafts((prev) => ({
|
|
4191
4219
|
...prev,
|
|
4192
|
-
[modelId]: formatCapacity$
|
|
4220
|
+
[modelId]: formatCapacity$3(parsed)
|
|
4193
4221
|
}));
|
|
4194
4222
|
notifyChange();
|
|
4195
4223
|
} catch (err) {
|
|
@@ -4218,7 +4246,7 @@ window.__ModuleLoader__.load({
|
|
|
4218
4246
|
const model = updated.models.find((candidate) => candidate.id === modelId);
|
|
4219
4247
|
return model === void 0 ? prev : {
|
|
4220
4248
|
...prev,
|
|
4221
|
-
[modelId]: formatCapacity$
|
|
4249
|
+
[modelId]: formatCapacity$3(model.defaultContextWindow)
|
|
4222
4250
|
};
|
|
4223
4251
|
});
|
|
4224
4252
|
notifyChange();
|
|
@@ -4241,7 +4269,7 @@ window.__ModuleLoader__.load({
|
|
|
4241
4269
|
body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
|
|
4242
4270
|
});
|
|
4243
4271
|
setStatus(updated);
|
|
4244
|
-
setContextDrafts(contextDraftsFor$
|
|
4272
|
+
setContextDrafts(contextDraftsFor$3(updated));
|
|
4245
4273
|
notifyChange();
|
|
4246
4274
|
} catch (err) {
|
|
4247
4275
|
reportError(err);
|
|
@@ -4632,7 +4660,7 @@ window.__ModuleLoader__.load({
|
|
|
4632
4660
|
title: model.id,
|
|
4633
4661
|
children: [model.name, model.defaultContextWindow < model.contextWindow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4634
4662
|
className: "dshcl-model-meta",
|
|
4635
|
-
children: formatCapacity$
|
|
4663
|
+
children: formatCapacity$3(model.contextWindow)
|
|
4636
4664
|
})]
|
|
4637
4665
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4638
4666
|
className: "dsha-capacity-control",
|
|
@@ -4820,7 +4848,7 @@ window.__ModuleLoader__.load({
|
|
|
4820
4848
|
}),
|
|
4821
4849
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4822
4850
|
className: "dsha-timestamp",
|
|
4823
|
-
children: quota.fetchedAt === null ? t.observedAt.replace("{time}", formatDate$
|
|
4851
|
+
children: quota.fetchedAt === null ? t.observedAt.replace("{time}", formatDate$3(quota.observedAt)) : t.updatedAt.replace("{time}", formatDate$3(quota.fetchedAt))
|
|
4824
4852
|
})
|
|
4825
4853
|
]
|
|
4826
4854
|
})
|
|
@@ -4845,7 +4873,7 @@ window.__ModuleLoader__.load({
|
|
|
4845
4873
|
//#endregion
|
|
4846
4874
|
//#region src/client/kimi-code/locales.ts
|
|
4847
4875
|
const NS_KIMI_CODE = "dsh-kimi-code";
|
|
4848
|
-
const zh$
|
|
4876
|
+
const zh$3 = {
|
|
4849
4877
|
...accountPoolZh,
|
|
4850
4878
|
title: "Kimi Code",
|
|
4851
4879
|
pageDesc: "登录 Kimi Code 订阅,管理模型、思考档位、上下文窗口与额度。",
|
|
@@ -4969,7 +4997,7 @@ window.__ModuleLoader__.load({
|
|
|
4969
4997
|
requests: "次请求",
|
|
4970
4998
|
tokens: "tokens"
|
|
4971
4999
|
};
|
|
4972
|
-
const en$
|
|
5000
|
+
const en$3 = {
|
|
4973
5001
|
...accountPoolEn,
|
|
4974
5002
|
title: "Kimi Code",
|
|
4975
5003
|
pageDesc: "Sign in to the Kimi Code subscription and manage models, thinking level, context windows, and quota.",
|
|
@@ -5093,11 +5121,11 @@ window.__ModuleLoader__.load({
|
|
|
5093
5121
|
requests: "requests",
|
|
5094
5122
|
tokens: "tokens"
|
|
5095
5123
|
};
|
|
5096
|
-
const dictionaries$
|
|
5097
|
-
zh: zh$
|
|
5098
|
-
"zh-CN": zh$
|
|
5099
|
-
en: en$
|
|
5100
|
-
"en-US": en$
|
|
5124
|
+
const dictionaries$3 = {
|
|
5125
|
+
zh: zh$3,
|
|
5126
|
+
"zh-CN": zh$3,
|
|
5127
|
+
en: en$3,
|
|
5128
|
+
"en-US": en$3
|
|
5101
5129
|
};
|
|
5102
5130
|
//#endregion
|
|
5103
5131
|
//#region src/client/kimi-code/KimiModelCapabilities.tsx
|
|
@@ -5110,7 +5138,7 @@ window.__ModuleLoader__.load({
|
|
|
5110
5138
|
* Capabilities are now short tags in their own columns, with the per-model
|
|
5111
5139
|
* detail kept in a hover title.
|
|
5112
5140
|
*/
|
|
5113
|
-
const t = zh$
|
|
5141
|
+
const t = zh$3;
|
|
5114
5142
|
function KimiModelCapabilities({ models }) {
|
|
5115
5143
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5116
5144
|
className: "dsha-cap-table",
|
|
@@ -5168,14 +5196,14 @@ window.__ModuleLoader__.load({
|
|
|
5168
5196
|
return json.value;
|
|
5169
5197
|
}
|
|
5170
5198
|
/** Parse "1M", "512K", "200000" into a positive integer token count. */
|
|
5171
|
-
function parsePositiveCapacity$
|
|
5199
|
+
function parsePositiveCapacity$2(value) {
|
|
5172
5200
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
5173
5201
|
if (matched === null) return null;
|
|
5174
5202
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
5175
5203
|
const parsed = Number(matched[1]) * multiplier;
|
|
5176
5204
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
5177
5205
|
}
|
|
5178
|
-
function formatCapacity$
|
|
5206
|
+
function formatCapacity$2(value) {
|
|
5179
5207
|
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
5180
5208
|
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
5181
5209
|
return String(value);
|
|
@@ -5185,12 +5213,12 @@ window.__ModuleLoader__.load({
|
|
|
5185
5213
|
* toggle: a model that was just enabled has no draft yet, and the context
|
|
5186
5214
|
* window section only renders enabled models.
|
|
5187
5215
|
*/
|
|
5188
|
-
function contextDraftsFor$
|
|
5216
|
+
function contextDraftsFor$2(status) {
|
|
5189
5217
|
const drafts = {};
|
|
5190
|
-
for (const model of status.models) drafts[model.id] = formatCapacity$
|
|
5218
|
+
for (const model of status.models) drafts[model.id] = formatCapacity$2(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
5191
5219
|
return drafts;
|
|
5192
5220
|
}
|
|
5193
|
-
function formatDate$
|
|
5221
|
+
function formatDate$2(ms) {
|
|
5194
5222
|
if (ms === void 0 || ms === null || ms <= 0) return "—";
|
|
5195
5223
|
try {
|
|
5196
5224
|
return new Intl.DateTimeFormat(void 0, {
|
|
@@ -5226,10 +5254,10 @@ window.__ModuleLoader__.load({
|
|
|
5226
5254
|
}
|
|
5227
5255
|
}
|
|
5228
5256
|
const EFFORT_LABEL = {
|
|
5229
|
-
low: zh$
|
|
5230
|
-
high: zh$
|
|
5231
|
-
max: zh$
|
|
5232
|
-
none: zh$
|
|
5257
|
+
low: zh$3.effortLow,
|
|
5258
|
+
high: zh$3.effortHigh,
|
|
5259
|
+
max: zh$3.effortMax,
|
|
5260
|
+
none: zh$3.effortNone
|
|
5233
5261
|
};
|
|
5234
5262
|
/** Human label for the last request's prefix-drift cause. */
|
|
5235
5263
|
function driftLabel(cause, t) {
|
|
@@ -5255,7 +5283,7 @@ window.__ModuleLoader__.load({
|
|
|
5255
5283
|
const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
|
|
5256
5284
|
/** Follow-up poll owed while the host refreshes the quota behind an answer. */
|
|
5257
5285
|
const quotaFollowUp = (0, react.useRef)(null);
|
|
5258
|
-
const t = zh$
|
|
5286
|
+
const t = zh$3;
|
|
5259
5287
|
const notifyChange = (0, react.useCallback)(() => {
|
|
5260
5288
|
onModelChange?.();
|
|
5261
5289
|
loadModelDirectory?.();
|
|
@@ -5265,7 +5293,7 @@ window.__ModuleLoader__.load({
|
|
|
5265
5293
|
try {
|
|
5266
5294
|
const data = await fetchApi$6("/status");
|
|
5267
5295
|
setStatus(data);
|
|
5268
|
-
setContextDrafts(contextDraftsFor$
|
|
5296
|
+
setContextDrafts(contextDraftsFor$2(data));
|
|
5269
5297
|
quotaFollowUp.current ??= createQuotaFollowUp();
|
|
5270
5298
|
quotaFollowUp.current.observe(data.quotaRefreshing === true, () => {
|
|
5271
5299
|
loadStatus(true);
|
|
@@ -5425,7 +5453,7 @@ window.__ModuleLoader__.load({
|
|
|
5425
5453
|
setError(null);
|
|
5426
5454
|
const updated = await fetchApi$6("/catalog/refresh", { method: "POST" });
|
|
5427
5455
|
setStatus(updated);
|
|
5428
|
-
setContextDrafts(contextDraftsFor$
|
|
5456
|
+
setContextDrafts(contextDraftsFor$2(updated));
|
|
5429
5457
|
notifyChange();
|
|
5430
5458
|
} catch (err) {
|
|
5431
5459
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -5454,7 +5482,7 @@ window.__ModuleLoader__.load({
|
|
|
5454
5482
|
body: JSON.stringify({ enabledModelIds })
|
|
5455
5483
|
});
|
|
5456
5484
|
setStatus(updated);
|
|
5457
|
-
setContextDrafts(contextDraftsFor$
|
|
5485
|
+
setContextDrafts(contextDraftsFor$2(updated));
|
|
5458
5486
|
notifyChange();
|
|
5459
5487
|
} catch (err) {
|
|
5460
5488
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -5501,7 +5529,7 @@ window.__ModuleLoader__.load({
|
|
|
5501
5529
|
};
|
|
5502
5530
|
const handleSaveContextWindow = async (modelId) => {
|
|
5503
5531
|
const raw = contextDrafts[modelId] || "";
|
|
5504
|
-
const parsed = parsePositiveCapacity$
|
|
5532
|
+
const parsed = parsePositiveCapacity$2(raw);
|
|
5505
5533
|
if (parsed === null) {
|
|
5506
5534
|
setError(`Invalid context capacity: ${raw}`);
|
|
5507
5535
|
return;
|
|
@@ -5516,7 +5544,7 @@ window.__ModuleLoader__.load({
|
|
|
5516
5544
|
setStatus(updated);
|
|
5517
5545
|
setContextDrafts((prev) => ({
|
|
5518
5546
|
...prev,
|
|
5519
|
-
[modelId]: formatCapacity$
|
|
5547
|
+
[modelId]: formatCapacity$2(parsed)
|
|
5520
5548
|
}));
|
|
5521
5549
|
notifyChange();
|
|
5522
5550
|
} catch (err) {
|
|
@@ -5539,7 +5567,7 @@ window.__ModuleLoader__.load({
|
|
|
5539
5567
|
const model = updated.models.find((candidate) => candidate.id === modelId);
|
|
5540
5568
|
return model === void 0 ? prev : {
|
|
5541
5569
|
...prev,
|
|
5542
|
-
[modelId]: formatCapacity$
|
|
5570
|
+
[modelId]: formatCapacity$2(model.defaultContextWindow)
|
|
5543
5571
|
};
|
|
5544
5572
|
});
|
|
5545
5573
|
notifyChange();
|
|
@@ -5562,7 +5590,7 @@ window.__ModuleLoader__.load({
|
|
|
5562
5590
|
body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
|
|
5563
5591
|
});
|
|
5564
5592
|
setStatus(updated);
|
|
5565
|
-
setContextDrafts(contextDraftsFor$
|
|
5593
|
+
setContextDrafts(contextDraftsFor$2(updated));
|
|
5566
5594
|
notifyChange();
|
|
5567
5595
|
} catch (err) {
|
|
5568
5596
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -5650,7 +5678,7 @@ window.__ModuleLoader__.load({
|
|
|
5650
5678
|
children: t.codeExpires
|
|
5651
5679
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5652
5680
|
className: "dsha-value",
|
|
5653
|
-
children: formatDate$
|
|
5681
|
+
children: formatDate$2(flow?.expiresAt)
|
|
5654
5682
|
})]
|
|
5655
5683
|
}),
|
|
5656
5684
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -5931,7 +5959,7 @@ window.__ModuleLoader__.load({
|
|
|
5931
5959
|
title: model.id,
|
|
5932
5960
|
children: [model.name, model.defaultContextWindow < model.contextWindow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5933
5961
|
className: "dsha-model-meta",
|
|
5934
|
-
children: formatCapacity$
|
|
5962
|
+
children: formatCapacity$2(model.contextWindow)
|
|
5935
5963
|
})]
|
|
5936
5964
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5937
5965
|
className: "dsha-capacity-control",
|
|
@@ -6073,67 +6101,1223 @@ window.__ModuleLoader__.load({
|
|
|
6073
6101
|
});
|
|
6074
6102
|
}
|
|
6075
6103
|
//#endregion
|
|
6076
|
-
//#region src/
|
|
6077
|
-
/**
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6104
|
+
//#region src/client/minimax-code/api.ts
|
|
6105
|
+
/**
|
|
6106
|
+
* The MiniMax Code routes the settings card consumes, in one place.
|
|
6107
|
+
*
|
|
6108
|
+
* Every path is prefixed with the frozen shared constant, so the client cannot
|
|
6109
|
+
* drift from the host's mount point. Answers are read tolerantly: the sibling
|
|
6110
|
+
* lines reply with an `{ ok, value }` envelope while this line's route table
|
|
6111
|
+
* documents the payload itself, and a card must not care which one arrived.
|
|
6112
|
+
*/
|
|
6113
|
+
/** A route's error field is a plain string on some routes and an object on others. */
|
|
6114
|
+
function errorMessage(value, fallback) {
|
|
6115
|
+
if (typeof value === "string" && value !== "") return value;
|
|
6116
|
+
if (value !== null && typeof value === "object") {
|
|
6117
|
+
const message = value.message;
|
|
6118
|
+
if (typeof message === "string" && message !== "") return message;
|
|
6119
|
+
}
|
|
6120
|
+
return fallback;
|
|
6121
|
+
}
|
|
6122
|
+
async function request(path, init) {
|
|
6123
|
+
const res = await fetch(`${MINIMAX_CODE_ROUTE_PREFIX}${path}`, {
|
|
6124
|
+
...init,
|
|
6125
|
+
credentials: "same-origin",
|
|
6126
|
+
headers: {
|
|
6127
|
+
"Content-Type": "application/json",
|
|
6128
|
+
...init?.headers
|
|
6129
|
+
}
|
|
6130
|
+
});
|
|
6131
|
+
const raw = await res.text();
|
|
6132
|
+
let body = null;
|
|
6133
|
+
try {
|
|
6134
|
+
body = raw === "" ? null : JSON.parse(raw);
|
|
6135
|
+
} catch {
|
|
6136
|
+
throw new Error(`HTTP ${res.status}`);
|
|
6137
|
+
}
|
|
6138
|
+
const envelope = body;
|
|
6139
|
+
if (envelope !== null && typeof envelope === "object" && typeof envelope.ok === "boolean" && "value" in envelope) {
|
|
6140
|
+
if (!res.ok || envelope.ok === false) throw new Error(errorMessage(envelope.error, `HTTP ${res.status}`));
|
|
6141
|
+
return envelope.value;
|
|
6142
|
+
}
|
|
6143
|
+
if (!res.ok) throw new Error(errorMessage(body?.error, `HTTP ${res.status}`));
|
|
6144
|
+
return body;
|
|
6145
|
+
}
|
|
6146
|
+
function get(path) {
|
|
6147
|
+
return request(path);
|
|
6148
|
+
}
|
|
6149
|
+
function post(path, body = {}) {
|
|
6150
|
+
return request(path, {
|
|
6151
|
+
method: "POST",
|
|
6152
|
+
body: JSON.stringify(body)
|
|
6153
|
+
});
|
|
6154
|
+
}
|
|
6155
|
+
function messageOf(cause) {
|
|
6156
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
6157
|
+
}
|
|
6086
6158
|
//#endregion
|
|
6087
|
-
//#region src/client/
|
|
6088
|
-
const
|
|
6089
|
-
const zh$
|
|
6090
|
-
|
|
6091
|
-
|
|
6159
|
+
//#region src/client/minimax-code/locales.ts
|
|
6160
|
+
const NS_MINIMAX_CODE = "dsh-minimax-code";
|
|
6161
|
+
const zh$2 = {
|
|
6162
|
+
...accountPoolZh,
|
|
6163
|
+
title: "MiniMax Code",
|
|
6164
|
+
pageDesc: "登录 MiniMax Code 编程订阅(设备码 OAuth),复用本机 MiniMax Code 的登录态,管理账号、连接与模型。",
|
|
6092
6165
|
account: "账号",
|
|
6093
|
-
|
|
6094
|
-
signedOut: "
|
|
6095
|
-
|
|
6096
|
-
|
|
6166
|
+
signedIn: "已登录",
|
|
6167
|
+
signedOut: "未登录",
|
|
6168
|
+
accountLabel: "账号标签",
|
|
6169
|
+
accountId: "账号 ID",
|
|
6170
|
+
email: "邮箱",
|
|
6097
6171
|
region: "区域",
|
|
6098
|
-
regionCn: "
|
|
6099
|
-
|
|
6100
|
-
accountType: "账号类型",
|
|
6101
|
-
sourceFile: "凭据文件",
|
|
6102
|
-
authDirectory: "凭据目录",
|
|
6172
|
+
regionCn: "中国大陆 (minimax.cn)",
|
|
6173
|
+
regionGlobal: "国际 (minimax.io)",
|
|
6103
6174
|
storage: "凭据存储",
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6175
|
+
storageNative: "MiniMax Code 原生凭据(~/.minimax/auth)",
|
|
6176
|
+
storageDpapi: "Windows DPAPI(当前用户加密)",
|
|
6177
|
+
storageFile: "本地凭据文件",
|
|
6178
|
+
storagePath: "凭据路径",
|
|
6179
|
+
expiresAt: "令牌到期",
|
|
6180
|
+
expiresRemaining: "剩余 {hours} 小时",
|
|
6181
|
+
expiresExpired: "已过期",
|
|
6182
|
+
expiresHint: "访问令牌约 24 小时有效;Host 会在令牌过期或上游返回 401 时自动刷新。刷新被拒绝时请回到 MiniMax Code 重新登录。",
|
|
6183
|
+
signIn: "登录 MiniMax Code",
|
|
6184
|
+
signingIn: "正在申请设备码...",
|
|
6185
|
+
signOut: "登出",
|
|
6186
|
+
cancelSignIn: "取消登录",
|
|
6187
|
+
deviceCodeSection: "设备码授权",
|
|
6188
|
+
deviceCodeHint: "在浏览器中打开下方链接(用户码已单独列出,可复制),用你的 MiniMax 账号确认授权。",
|
|
6189
|
+
userCode: "用户码",
|
|
6190
|
+
copyCode: "复制用户码",
|
|
6191
|
+
copied: "已复制",
|
|
6192
|
+
openSignInPage: "打开授权页面",
|
|
6193
|
+
codeExpires: "设备码有效期",
|
|
6194
|
+
codeMinutes: "剩余 {minutes} 分钟",
|
|
6195
|
+
waitingAuthorization: "等待浏览器授权...",
|
|
6196
|
+
loginFailed: "登录失败",
|
|
6197
|
+
loginExpired: "设备码已过期,请重新发起登录。",
|
|
6198
|
+
loginDenied: "授权被拒绝。",
|
|
6199
|
+
logoutOwnedByApp: "当前登录态属于 MiniMax Code 桌面端:本插件复用它并会在需要时续期写回,但不会撤销或删除它(那会把你从正在运行的 MiniMax Code 里踢下线)。请在 MiniMax Code 应用中退出登录。",
|
|
6121
6200
|
connection: "连接",
|
|
6122
6201
|
provider: "Provider",
|
|
6123
|
-
providerValue: "WorkBuddy Subscription · workbuddy-subscription",
|
|
6124
6202
|
connectionState: "连接状态",
|
|
6125
6203
|
connected: "已连接",
|
|
6126
6204
|
untested: "未测试",
|
|
6205
|
+
routeOwned: "本插件正在服务该模型路由。",
|
|
6206
|
+
routeConflict: "模型路由已被其他 Provider 占用:{detail}。请在 DSH 设置中移除重复的 Provider 配置后重新加载。",
|
|
6127
6207
|
testConnection: "测试连接",
|
|
6128
6208
|
testingConnection: "测试中...",
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6209
|
+
testSuccess: "连接正常",
|
|
6210
|
+
testSuccessModel: "连接正常({model})",
|
|
6211
|
+
testFailed: "连接失败",
|
|
6132
6212
|
modelsSection: "模型",
|
|
6213
|
+
modelsHint: "模型目录由本线路硬编码(MiniMax Code 未开放 /v1/models 接口),当前共 {count} 个可用模型。勾选后模型才会出现在对话页的模型选择列表中;未勾选或关闭下方「启用此供应商」可在列表中隐藏该线路。",
|
|
6214
|
+
modelsUnavailable: "暂无可显示的模型。",
|
|
6215
|
+
quotaSection: "用量与配额",
|
|
6216
|
+
quotaUnavailable: "暂时没有用量数据。",
|
|
6217
|
+
quotaNeedsApiKey: "上游拒绝了这个登录态读取用量(官方客户端的用量端点要求带官方客户端标识头,本插件默认不伪造)。请在 MiniMax 控制台的用量条里查看 Token Plan 用量;如果你接受该取舍,可设 DSH_MINIMAX_CODE_QUOTA_ATTRIBUTION=1 后重试。",
|
|
6218
|
+
quotaUnreachable: "暂时读不到用量(用量端点未应答),稍后会自动重试。",
|
|
6219
|
+
quotaUsed: "已用 {percent}%",
|
|
6220
|
+
quotaRemaining: "剩余 {percent}%",
|
|
6221
|
+
quotaReset: "重置:{time}",
|
|
6222
|
+
quotaRefresh: "刷新用量",
|
|
6223
|
+
quotaRefreshing: "刷新中...",
|
|
6224
|
+
quotaWindowInterval: "5 小时窗口",
|
|
6225
|
+
quotaWindowWeekly: "每周窗口",
|
|
6226
|
+
quotaUnlimited: "不限量",
|
|
6227
|
+
quotaCounts: "已用 {used} / {total}",
|
|
6228
|
+
composerLabel: "额度",
|
|
6133
6229
|
enableProvider: "启用此供应商",
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6230
|
+
selectAll: "全选",
|
|
6231
|
+
unselectAll: "全不选",
|
|
6232
|
+
enhanced: "增强功能",
|
|
6233
|
+
defaultReasoningEffort: "默认思考深度",
|
|
6234
|
+
defaultReasoningEffortHint: "控制支持推理的模型在未单独指定时的思考强度。",
|
|
6235
|
+
defaultEffortAuto: "自动(各模型默认)",
|
|
6236
|
+
contextWindowSection: "模型上下文窗口",
|
|
6237
|
+
contextWindowHint: "默认值来自订阅网关的模型目录(每个模型的真实上下文上限);可覆盖为自定义容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
|
|
6238
|
+
contextWindowNoneEnabled: "尚未勾选任何模型,先在上方「模型」中勾选。",
|
|
6239
|
+
contextWindowReset: "恢复默认",
|
|
6240
|
+
contextWindowResetAll: "全部恢复默认",
|
|
6241
|
+
tokens: "tokens",
|
|
6242
|
+
save: "保存",
|
|
6243
|
+
saving: "保存中...",
|
|
6244
|
+
invalidCapacity: "容量格式无效:{value}",
|
|
6245
|
+
thinkingAlwaysOn: "恒定开启(无档位)",
|
|
6246
|
+
thinkingToggle: "可关闭",
|
|
6247
|
+
thinkingForced: "强制开启(可选档位)",
|
|
6248
|
+
capText: "文本",
|
|
6249
|
+
capImage: "图片",
|
|
6250
|
+
loading: "加载中...",
|
|
6251
|
+
unknown: "—"
|
|
6252
|
+
};
|
|
6253
|
+
const en$2 = {
|
|
6254
|
+
...accountPoolEn,
|
|
6255
|
+
title: "MiniMax Code",
|
|
6256
|
+
pageDesc: "Sign in to the MiniMax Code coding subscription (device-code OAuth) and reuse the local MiniMax Code sign-in to manage the account, connection, and models.",
|
|
6257
|
+
account: "Account",
|
|
6258
|
+
signedIn: "Signed in",
|
|
6259
|
+
signedOut: "Not signed in",
|
|
6260
|
+
accountLabel: "Account label",
|
|
6261
|
+
accountId: "Account ID",
|
|
6262
|
+
email: "Email",
|
|
6263
|
+
region: "Region",
|
|
6264
|
+
regionCn: "Mainland China (minimax.cn)",
|
|
6265
|
+
regionGlobal: "Global (minimax.io)",
|
|
6266
|
+
storage: "Credential storage",
|
|
6267
|
+
storageNative: "MiniMax Code native credential (~/.minimax/auth)",
|
|
6268
|
+
storageDpapi: "Windows DPAPI (current-user encrypted)",
|
|
6269
|
+
storageFile: "Local credential file",
|
|
6270
|
+
storagePath: "Credential path",
|
|
6271
|
+
expiresAt: "Token expires",
|
|
6272
|
+
expiresRemaining: "{hours} h left",
|
|
6273
|
+
expiresExpired: "Expired",
|
|
6274
|
+
expiresHint: "The access token lives about 24 hours; the Host refreshes it once it expires or the upstream answers 401. When a refresh is rejected, sign in again from MiniMax Code.",
|
|
6275
|
+
signIn: "Sign in to MiniMax Code",
|
|
6276
|
+
signingIn: "Requesting a device code...",
|
|
6277
|
+
signOut: "Sign out",
|
|
6278
|
+
cancelSignIn: "Cancel",
|
|
6279
|
+
deviceCodeSection: "Device authorization",
|
|
6280
|
+
deviceCodeHint: "Open the link below in a browser (the user code is listed separately so it can be copied) and approve it with your MiniMax account.",
|
|
6281
|
+
userCode: "User code",
|
|
6282
|
+
copyCode: "Copy user code",
|
|
6283
|
+
copied: "Copied",
|
|
6284
|
+
openSignInPage: "Open the sign-in page",
|
|
6285
|
+
codeExpires: "Device code expires",
|
|
6286
|
+
codeMinutes: "{minutes} min left",
|
|
6287
|
+
waitingAuthorization: "Waiting for browser authorization...",
|
|
6288
|
+
loginFailed: "Sign-in failed",
|
|
6289
|
+
loginExpired: "The device code expired — start the sign-in again.",
|
|
6290
|
+
loginDenied: "Authorization was denied.",
|
|
6291
|
+
logoutOwnedByApp: "This sign-in belongs to the MiniMax Code desktop app. This plugin reuses it and renews it in place when needed, but it will not revoke or delete it (doing so would sign you out of the running MiniMax Code app). Sign out in the MiniMax Code app instead.",
|
|
6292
|
+
connection: "Connection",
|
|
6293
|
+
provider: "Provider",
|
|
6294
|
+
connectionState: "Connection state",
|
|
6295
|
+
connected: "Connected",
|
|
6296
|
+
untested: "Untested",
|
|
6297
|
+
routeOwned: "This plugin serves the model route.",
|
|
6298
|
+
routeConflict: "Another provider already owns the model route: {detail}. Remove the duplicate provider configuration in DSH settings and reload.",
|
|
6299
|
+
testConnection: "Test connection",
|
|
6300
|
+
testingConnection: "Testing...",
|
|
6301
|
+
testSuccess: "Connection OK",
|
|
6302
|
+
testSuccessModel: "Connection OK ({model})",
|
|
6303
|
+
testFailed: "Connection failed",
|
|
6304
|
+
modelsSection: "Models",
|
|
6305
|
+
modelsHint: "The catalog is hardcoded on this line (MiniMax Code exposes no /v1/models endpoint): {count} models available. Only checked models appear in the conversation model picker; unchecking or switching off \"Enable this provider\" hides the line from the list.",
|
|
6306
|
+
modelsUnavailable: "No model to show yet.",
|
|
6307
|
+
quotaSection: "Usage & quota",
|
|
6308
|
+
quotaUnavailable: "No usage data yet.",
|
|
6309
|
+
quotaNeedsApiKey: "The service refused this sign-in for the usage read (the official client's endpoint expects first-party attribution headers, which this plugin does not forge by default). Check the usage bar in the MiniMax console; if you accept that trade, set DSH_MINIMAX_CODE_QUOTA_ATTRIBUTION=1 and retry.",
|
|
6310
|
+
quotaUnreachable: "Usage is temporarily unreadable (the usage endpoint did not answer); this retries on its own.",
|
|
6311
|
+
quotaUsed: "{percent}% used",
|
|
6312
|
+
quotaRemaining: "{percent}% left",
|
|
6313
|
+
quotaReset: "Resets: {time}",
|
|
6314
|
+
quotaRefresh: "Refresh usage",
|
|
6315
|
+
quotaRefreshing: "Refreshing...",
|
|
6316
|
+
quotaWindowInterval: "5-hour window",
|
|
6317
|
+
quotaWindowWeekly: "Weekly window",
|
|
6318
|
+
quotaUnlimited: "Unlimited",
|
|
6319
|
+
quotaCounts: "{used} / {total} used",
|
|
6320
|
+
composerLabel: "Quota",
|
|
6321
|
+
enableProvider: "Enable this provider",
|
|
6322
|
+
selectAll: "Select all",
|
|
6323
|
+
unselectAll: "Unselect all",
|
|
6324
|
+
enhanced: "Enhanced",
|
|
6325
|
+
defaultReasoningEffort: "Default reasoning effort",
|
|
6326
|
+
defaultReasoningEffortHint: "Thinking strength for reasoning models when the conversation does not pick one.",
|
|
6327
|
+
defaultEffortAuto: "Auto (each model default)",
|
|
6328
|
+
contextWindowSection: "Model context windows",
|
|
6329
|
+
contextWindowHint: "Defaults come from the subscription gateway model directory (each model's real upper bound). Override one to a custom capacity; the value feeds the compression and overflow decisions. Accepts 1M, 512K, 200K and similar.",
|
|
6330
|
+
contextWindowNoneEnabled: "No model is checked yet — pick one in \"Models\" above.",
|
|
6331
|
+
contextWindowReset: "Restore default",
|
|
6332
|
+
contextWindowResetAll: "Restore all defaults",
|
|
6333
|
+
tokens: "tokens",
|
|
6334
|
+
save: "Save",
|
|
6335
|
+
saving: "Saving...",
|
|
6336
|
+
invalidCapacity: "Invalid capacity: {value}",
|
|
6337
|
+
thinkingAlwaysOn: "Always on (no level)",
|
|
6338
|
+
thinkingToggle: "Can be disabled",
|
|
6339
|
+
thinkingForced: "Forced on (level selectable)",
|
|
6340
|
+
capText: "Text",
|
|
6341
|
+
capImage: "Image",
|
|
6342
|
+
loading: "Loading...",
|
|
6343
|
+
unknown: "—"
|
|
6344
|
+
};
|
|
6345
|
+
const dictionaries$2 = {
|
|
6346
|
+
zh: zh$2,
|
|
6347
|
+
"zh-CN": zh$2,
|
|
6348
|
+
en: en$2,
|
|
6349
|
+
"en-US": en$2
|
|
6350
|
+
};
|
|
6351
|
+
//#endregion
|
|
6352
|
+
//#region src/client/minimax-code/MinimaxCodeSection.tsx
|
|
6353
|
+
/**
|
|
6354
|
+
* The shared pool card's labels, resolved through this card's dictionary.
|
|
6355
|
+
*
|
|
6356
|
+
* The sibling tabs hand the shared card their raw `zh` object, which works because
|
|
6357
|
+
* they render `zh` directly. This card renders through a translate function
|
|
6358
|
+
* instead, so the same label set is assembled here by looking each key up. It is
|
|
6359
|
+
* derived from the shared ZH label object's own keys, so a label added to the
|
|
6360
|
+
* shared card cannot be silently missed — the `satisfies` below turns that into a
|
|
6361
|
+
* compile error.
|
|
6362
|
+
*/
|
|
6363
|
+
function accountPoolLabelsFor(t) {
|
|
6364
|
+
return {
|
|
6365
|
+
accountPool: t("accountPool"),
|
|
6366
|
+
addAccount: t("addAccount"),
|
|
6367
|
+
accountCount: t("accountCount"),
|
|
6368
|
+
primaryAccount: t("primaryAccount"),
|
|
6369
|
+
activeAccount: t("activeAccount"),
|
|
6370
|
+
setPrimary: t("setPrimary"),
|
|
6371
|
+
deleteAccount: t("deleteAccount"),
|
|
6372
|
+
cooling: t("cooling"),
|
|
6373
|
+
cooldownLeft: t("cooldownLeft"),
|
|
6374
|
+
clearCooldown: t("clearCooldown"),
|
|
6375
|
+
needsRelogin: t("needsRelogin"),
|
|
6376
|
+
relogin: t("relogin"),
|
|
6377
|
+
rotationStrategy: t("rotationStrategy"),
|
|
6378
|
+
strategySequential: t("strategySequential"),
|
|
6379
|
+
strategyRoundRobin: t("strategyRoundRobin"),
|
|
6380
|
+
strategySticky: t("strategySticky"),
|
|
6381
|
+
noAccounts: t("noAccounts"),
|
|
6382
|
+
storage: t("storage"),
|
|
6383
|
+
storageNotice: t("storageNotice"),
|
|
6384
|
+
email: t("email"),
|
|
6385
|
+
expires: t("expiresAt"),
|
|
6386
|
+
lastUsed: t("lastUsed"),
|
|
6387
|
+
accountId: t("accountId")
|
|
6388
|
+
};
|
|
6389
|
+
}
|
|
6390
|
+
/** Device-code poll cadence. The host owns the real expiry. */
|
|
6391
|
+
const LOGIN_POLL_INTERVAL_MS = 2e3;
|
|
6392
|
+
/**
|
|
6393
|
+
* Parse "1M", "512K", "200000" into a positive integer token count.
|
|
6394
|
+
*
|
|
6395
|
+
* Every provider card carries its own copy of this pair rather than importing one
|
|
6396
|
+
* from a shared module; the value is user input in a free-text field and a bad
|
|
6397
|
+
* parse silently corrupts the overflow judgement, so it stays next to the only
|
|
6398
|
+
* field that produces it.
|
|
6399
|
+
*/
|
|
6400
|
+
function parsePositiveCapacity$1(value) {
|
|
6401
|
+
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
6402
|
+
if (matched === null) return null;
|
|
6403
|
+
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
6404
|
+
const parsed = Number(matched[1]) * multiplier;
|
|
6405
|
+
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
6406
|
+
}
|
|
6407
|
+
/** Render a token capacity the way the capacity field seeds itself. */
|
|
6408
|
+
function formatCapacity$1(value) {
|
|
6409
|
+
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
6410
|
+
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
6411
|
+
return String(value);
|
|
6412
|
+
}
|
|
6413
|
+
/**
|
|
6414
|
+
* Seed one draft per model from a status payload.
|
|
6415
|
+
*
|
|
6416
|
+
* Run after a model toggle too: a model that was just enabled has no draft yet,
|
|
6417
|
+
* and the context-window section only renders enabled models.
|
|
6418
|
+
*/
|
|
6419
|
+
function contextDraftsFor$1(status) {
|
|
6420
|
+
const drafts = {};
|
|
6421
|
+
for (const model of status.models) drafts[model.id] = formatCapacity$1(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
6422
|
+
return drafts;
|
|
6423
|
+
}
|
|
6424
|
+
/** Human label per thinking mode, so the card states what the model does. */
|
|
6425
|
+
function thinkingLabel(mode, t) {
|
|
6426
|
+
if (mode === "always-on") return t("thinkingAlwaysOn");
|
|
6427
|
+
if (mode === "forced-effort") return t("thinkingForced");
|
|
6428
|
+
return t("thinkingToggle");
|
|
6429
|
+
}
|
|
6430
|
+
/** The card's own dictionary; stable identity keeps effect dependencies intact. */
|
|
6431
|
+
const fallbackTranslate = (key) => zh$2[key];
|
|
6432
|
+
/**
|
|
6433
|
+
* Hours still left on the access token, or null once it has run out.
|
|
6434
|
+
*
|
|
6435
|
+
* MiniMax Code's token lives about 24 hours, so hours are the unit the card
|
|
6436
|
+
* reports; a value worth a fraction of an hour keeps one decimal instead of
|
|
6437
|
+
* rounding down to 0.
|
|
6438
|
+
*/
|
|
6439
|
+
function remainingHours(expiresAtMs) {
|
|
6440
|
+
if (expiresAtMs === void 0 || !Number.isFinite(expiresAtMs) || expiresAtMs <= 0) return null;
|
|
6441
|
+
const hours = (expiresAtMs - Date.now()) / 36e5;
|
|
6442
|
+
if (hours <= 0) return null;
|
|
6443
|
+
return hours >= 10 ? hours.toFixed(0) : hours.toFixed(1);
|
|
6444
|
+
}
|
|
6445
|
+
function storageLabel(storage, t) {
|
|
6446
|
+
if (storage === void 0) return t("unknown");
|
|
6447
|
+
switch (storage.kind) {
|
|
6448
|
+
case "minimax-native": return t("storageNative");
|
|
6449
|
+
case "dpapi": return t("storageDpapi");
|
|
6450
|
+
default: return t("storageFile");
|
|
6451
|
+
}
|
|
6452
|
+
}
|
|
6453
|
+
function formatDate$1(ms) {
|
|
6454
|
+
if (ms === void 0 || !Number.isFinite(ms) || ms <= 0) return "—";
|
|
6455
|
+
try {
|
|
6456
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
6457
|
+
dateStyle: "medium",
|
|
6458
|
+
timeStyle: "short"
|
|
6459
|
+
}).format(ms);
|
|
6460
|
+
} catch {
|
|
6461
|
+
return "—";
|
|
6462
|
+
}
|
|
6463
|
+
}
|
|
6464
|
+
function MinimaxCodeSection({ onModelChange }) {
|
|
6465
|
+
const t = fallbackTranslate;
|
|
6466
|
+
const [status, setStatus] = (0, react.useState)(null);
|
|
6467
|
+
const [loading, setLoading] = (0, react.useState)(true);
|
|
6468
|
+
const [busy, setBusy] = (0, react.useState)(null);
|
|
6469
|
+
const [error, setError] = (0, react.useState)(null);
|
|
6470
|
+
const [flow, setFlow] = (0, react.useState)(null);
|
|
6471
|
+
const [copied, setCopied] = (0, react.useState)(false);
|
|
6472
|
+
const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
|
|
6473
|
+
const [contextDrafts, setContextDrafts] = (0, react.useState)({});
|
|
6474
|
+
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
6475
|
+
const [pool, setPool] = (0, react.useState)(void 0);
|
|
6476
|
+
const loadStatus = (0, react.useCallback)(async (quiet = false) => {
|
|
6477
|
+
if (!quiet) setError(null);
|
|
6478
|
+
try {
|
|
6479
|
+
const next = await get("/status");
|
|
6480
|
+
setStatus(next);
|
|
6481
|
+
setContextDrafts(contextDraftsFor$1(next));
|
|
6482
|
+
} catch (cause) {
|
|
6483
|
+
if (!quiet) setError(messageOf(cause));
|
|
6484
|
+
} finally {
|
|
6485
|
+
setLoading(false);
|
|
6486
|
+
}
|
|
6487
|
+
}, []);
|
|
6488
|
+
(0, react.useEffect)(() => {
|
|
6489
|
+
loadStatus();
|
|
6490
|
+
loadPool();
|
|
6491
|
+
const refreshWhenVisible = () => {
|
|
6492
|
+
if (document.visibilityState === "visible") {
|
|
6493
|
+
loadStatus(true);
|
|
6494
|
+
loadPool();
|
|
6495
|
+
}
|
|
6496
|
+
};
|
|
6497
|
+
document.addEventListener("visibilitychange", refreshWhenVisible);
|
|
6498
|
+
const timer = window.setInterval(refreshWhenVisible, 6e4);
|
|
6499
|
+
return () => {
|
|
6500
|
+
window.clearInterval(timer);
|
|
6501
|
+
document.removeEventListener("visibilitychange", refreshWhenVisible);
|
|
6502
|
+
};
|
|
6503
|
+
}, [loadStatus]);
|
|
6504
|
+
const loginId = flow?.loginId;
|
|
6505
|
+
(0, react.useEffect)(() => {
|
|
6506
|
+
if (loginId === void 0) return;
|
|
6507
|
+
let stopped = false;
|
|
6508
|
+
const timer = window.setInterval(() => {
|
|
6509
|
+
(async () => {
|
|
6510
|
+
try {
|
|
6511
|
+
const poll = await post("/login/poll", { loginId });
|
|
6512
|
+
if (stopped || poll.status === "pending") return;
|
|
6513
|
+
stopped = true;
|
|
6514
|
+
window.clearInterval(timer);
|
|
6515
|
+
setFlow(null);
|
|
6516
|
+
if (poll.status === "authenticated") {
|
|
6517
|
+
await loadStatus();
|
|
6518
|
+
onModelChange?.();
|
|
6519
|
+
return;
|
|
6520
|
+
}
|
|
6521
|
+
setError(poll.status === "expired" ? t("loginExpired") : t("loginDenied"));
|
|
6522
|
+
} catch {}
|
|
6523
|
+
})();
|
|
6524
|
+
}, LOGIN_POLL_INTERVAL_MS);
|
|
6525
|
+
return () => {
|
|
6526
|
+
stopped = true;
|
|
6527
|
+
window.clearInterval(timer);
|
|
6528
|
+
};
|
|
6529
|
+
}, [
|
|
6530
|
+
loginId,
|
|
6531
|
+
loadStatus,
|
|
6532
|
+
onModelChange,
|
|
6533
|
+
t
|
|
6534
|
+
]);
|
|
6535
|
+
/**
|
|
6536
|
+
* Fetch the usage snapshot once, the first time the card sees a signed-in
|
|
6537
|
+
* account without one.
|
|
6538
|
+
*
|
|
6539
|
+
* The status route refreshes usage BEHIND its answer, so it never blocks on a
|
|
6540
|
+
* network read; that means the very first paint has no snapshot. Asking here
|
|
6541
|
+
* fills the section immediately instead of leaving it empty for a whole poll
|
|
6542
|
+
* interval. A failure is silent on purpose: the section already explains that no
|
|
6543
|
+
* usage is available, and a usage read must never surface as an error banner.
|
|
6544
|
+
*/
|
|
6545
|
+
const authenticated = status?.authenticated === true;
|
|
6546
|
+
const quotaRequested = (0, react.useRef)(false);
|
|
6547
|
+
(0, react.useEffect)(() => {
|
|
6548
|
+
if (quotaRequested.current || !authenticated || status?.quota !== void 0) return;
|
|
6549
|
+
quotaRequested.current = true;
|
|
6550
|
+
(async () => {
|
|
6551
|
+
try {
|
|
6552
|
+
setStatus(await post("/quota"));
|
|
6553
|
+
} catch {}
|
|
6554
|
+
})();
|
|
6555
|
+
}, [authenticated, status?.quota]);
|
|
6556
|
+
const handleLogin = async () => {
|
|
6557
|
+
try {
|
|
6558
|
+
setBusy("login");
|
|
6559
|
+
setError(null);
|
|
6560
|
+
setConnectionNotice(null);
|
|
6561
|
+
setCopied(false);
|
|
6562
|
+
const started = await post("/login/start");
|
|
6563
|
+
const login = started.login ?? (typeof started.loginId === "string" ? started : void 0);
|
|
6564
|
+
if (login === void 0) {
|
|
6565
|
+
setError(t("loginFailed"));
|
|
6566
|
+
return;
|
|
6567
|
+
}
|
|
6568
|
+
setFlow(login);
|
|
6569
|
+
} catch (cause) {
|
|
6570
|
+
setError(messageOf(cause));
|
|
6571
|
+
} finally {
|
|
6572
|
+
setBusy(null);
|
|
6573
|
+
}
|
|
6574
|
+
};
|
|
6575
|
+
const handleCancelLogin = async () => {
|
|
6576
|
+
const pending = flow;
|
|
6577
|
+
setFlow(null);
|
|
6578
|
+
if (pending === null) return;
|
|
6579
|
+
try {
|
|
6580
|
+
await post("/login/cancel", { loginId: pending.loginId });
|
|
6581
|
+
} catch (cause) {
|
|
6582
|
+
setError(messageOf(cause));
|
|
6583
|
+
}
|
|
6584
|
+
};
|
|
6585
|
+
const handleCopyCode = async () => {
|
|
6586
|
+
const code = flow?.userCode;
|
|
6587
|
+
if (code === void 0 || code === "") return;
|
|
6588
|
+
try {
|
|
6589
|
+
await navigator.clipboard.writeText(code);
|
|
6590
|
+
setCopied(true);
|
|
6591
|
+
window.setTimeout(() => setCopied(false), 2e3);
|
|
6592
|
+
} catch {}
|
|
6593
|
+
};
|
|
6594
|
+
const handleLogout = async () => {
|
|
6595
|
+
try {
|
|
6596
|
+
setBusy("logout");
|
|
6597
|
+
setError(null);
|
|
6598
|
+
setConnectionNotice(null);
|
|
6599
|
+
setFlow(null);
|
|
6600
|
+
const result = await post("/logout");
|
|
6601
|
+
if (result.native === true) setConnectionNotice(result.error ?? t("logoutOwnedByApp"));
|
|
6602
|
+
await loadStatus(true);
|
|
6603
|
+
onModelChange?.();
|
|
6604
|
+
} catch (cause) {
|
|
6605
|
+
setError(messageOf(cause));
|
|
6606
|
+
await loadStatus(true);
|
|
6607
|
+
} finally {
|
|
6608
|
+
setBusy(null);
|
|
6609
|
+
}
|
|
6610
|
+
};
|
|
6611
|
+
/**
|
|
6612
|
+
* Apply one model-selection patch through `/models`.
|
|
6613
|
+
*
|
|
6614
|
+
* The host owns the selection and answers with the whole fresh status, so the
|
|
6615
|
+
* card never guesses which ids ended up enabled.
|
|
6616
|
+
*/
|
|
6617
|
+
/** Re-read the pool slice, which lives beside the status on its own route. */
|
|
6618
|
+
const loadPool = (0, react.useCallback)(async () => {
|
|
6619
|
+
try {
|
|
6620
|
+
const next = await get("/accounts");
|
|
6621
|
+
setPool(next);
|
|
6622
|
+
} catch {
|
|
6623
|
+
setPool(void 0);
|
|
6624
|
+
}
|
|
6625
|
+
}, []);
|
|
6626
|
+
/** Run one account action, then re-read both the pool and the status. */
|
|
6627
|
+
const poolAction = async (action, accountId) => {
|
|
6628
|
+
try {
|
|
6629
|
+
setBusy(action);
|
|
6630
|
+
setError(null);
|
|
6631
|
+
await post("/accounts", {
|
|
6632
|
+
action,
|
|
6633
|
+
accountId
|
|
6634
|
+
});
|
|
6635
|
+
await loadPool();
|
|
6636
|
+
await loadStatus(true);
|
|
6637
|
+
onModelChange?.();
|
|
6638
|
+
} catch (cause) {
|
|
6639
|
+
setError(messageOf(cause));
|
|
6640
|
+
} finally {
|
|
6641
|
+
setBusy(null);
|
|
6642
|
+
}
|
|
6643
|
+
};
|
|
6644
|
+
const poolSetStrategy = async (strategy) => {
|
|
6645
|
+
try {
|
|
6646
|
+
setBusy("strategy");
|
|
6647
|
+
setError(null);
|
|
6648
|
+
await post("/accounts", {
|
|
6649
|
+
action: "strategy",
|
|
6650
|
+
strategy
|
|
6651
|
+
});
|
|
6652
|
+
await loadPool();
|
|
6653
|
+
} catch (cause) {
|
|
6654
|
+
setError(messageOf(cause));
|
|
6655
|
+
} finally {
|
|
6656
|
+
setBusy(null);
|
|
6657
|
+
}
|
|
6658
|
+
};
|
|
6659
|
+
const applyEnabled = async (enabledModelIds) => {
|
|
6660
|
+
try {
|
|
6661
|
+
setError(null);
|
|
6662
|
+
const updated = await post("/models", { enabledModelIds });
|
|
6663
|
+
setStatus(updated);
|
|
6664
|
+
setContextDrafts(contextDraftsFor$1(updated));
|
|
6665
|
+
onModelChange?.();
|
|
6666
|
+
} catch (cause) {
|
|
6667
|
+
setError(messageOf(cause));
|
|
6668
|
+
}
|
|
6669
|
+
};
|
|
6670
|
+
/**
|
|
6671
|
+
* Flip the line's own switch.
|
|
6672
|
+
*
|
|
6673
|
+
* Optimistic on purpose: the checkbox is the one control whose state the user
|
|
6674
|
+
* is looking straight at, and a failed round trip re-reads the truth below
|
|
6675
|
+
* rather than leaving the box in a state the host never accepted.
|
|
6676
|
+
*/
|
|
6677
|
+
const toggleEnabled = async (enabled) => {
|
|
6678
|
+
setStatus((prev) => prev === null ? prev : {
|
|
6679
|
+
...prev,
|
|
6680
|
+
enabled
|
|
6681
|
+
});
|
|
6682
|
+
try {
|
|
6683
|
+
setError(null);
|
|
6684
|
+
const updated = await post("/settings", { enabled });
|
|
6685
|
+
setStatus(updated);
|
|
6686
|
+
onModelChange?.();
|
|
6687
|
+
} catch (cause) {
|
|
6688
|
+
setError(messageOf(cause));
|
|
6689
|
+
await loadStatus(true);
|
|
6690
|
+
}
|
|
6691
|
+
};
|
|
6692
|
+
const toggleModel = (modelId, checked) => {
|
|
6693
|
+
if (status === null) return;
|
|
6694
|
+
const current = status.models.filter((model) => model.enabled).map((model) => model.id);
|
|
6695
|
+
const next = checked ? [.../* @__PURE__ */ new Set([...current, modelId])] : current.filter((id) => id !== modelId);
|
|
6696
|
+
applyEnabled(next);
|
|
6697
|
+
};
|
|
6698
|
+
const setAllModels = (selectAll) => {
|
|
6699
|
+
if (status === null || status.models.length === 0) return;
|
|
6700
|
+
applyEnabled(selectAll ? status.models.map((model) => model.id) : []);
|
|
6701
|
+
};
|
|
6702
|
+
const handleUpdateEffort = async (effort) => {
|
|
6703
|
+
try {
|
|
6704
|
+
setError(null);
|
|
6705
|
+
const updated = await post("/settings", { defaultReasoningEffort: effort });
|
|
6706
|
+
setStatus(updated);
|
|
6707
|
+
onModelChange?.();
|
|
6708
|
+
} catch (cause) {
|
|
6709
|
+
setError(messageOf(cause));
|
|
6710
|
+
}
|
|
6711
|
+
};
|
|
6712
|
+
const handleSaveContextWindow = async (modelId) => {
|
|
6713
|
+
const raw = contextDrafts[modelId] ?? "";
|
|
6714
|
+
const parsed = parsePositiveCapacity$1(raw);
|
|
6715
|
+
if (parsed === null) {
|
|
6716
|
+
setError(t("invalidCapacity").replace("{value}", raw));
|
|
6717
|
+
return;
|
|
6718
|
+
}
|
|
6719
|
+
try {
|
|
6720
|
+
setSavingModel(modelId);
|
|
6721
|
+
setError(null);
|
|
6722
|
+
const updated = await post("/settings", { contextWindowOverrides: { [modelId]: parsed } });
|
|
6723
|
+
setStatus(updated);
|
|
6724
|
+
setContextDrafts((prev) => ({
|
|
6725
|
+
...prev,
|
|
6726
|
+
[modelId]: formatCapacity$1(parsed)
|
|
6727
|
+
}));
|
|
6728
|
+
onModelChange?.();
|
|
6729
|
+
} catch (cause) {
|
|
6730
|
+
setError(messageOf(cause));
|
|
6731
|
+
} finally {
|
|
6732
|
+
setSavingModel(null);
|
|
6733
|
+
}
|
|
6734
|
+
};
|
|
6735
|
+
const handleResetContextWindow = async (modelId) => {
|
|
6736
|
+
try {
|
|
6737
|
+
setSavingModel(modelId);
|
|
6738
|
+
setError(null);
|
|
6739
|
+
const updated = await post("/settings", { contextWindowOverrides: { [modelId]: null } });
|
|
6740
|
+
setStatus(updated);
|
|
6741
|
+
const model = updated.models.find((entry) => entry.id === modelId);
|
|
6742
|
+
if (model !== void 0) setContextDrafts((prev) => ({
|
|
6743
|
+
...prev,
|
|
6744
|
+
[modelId]: formatCapacity$1(model.defaultContextWindow)
|
|
6745
|
+
}));
|
|
6746
|
+
onModelChange?.();
|
|
6747
|
+
} catch (cause) {
|
|
6748
|
+
setError(messageOf(cause));
|
|
6749
|
+
} finally {
|
|
6750
|
+
setSavingModel(null);
|
|
6751
|
+
}
|
|
6752
|
+
};
|
|
6753
|
+
const handleResetAllContextWindows = async () => {
|
|
6754
|
+
const ids = Object.keys(status?.contextWindowOverrides ?? {});
|
|
6755
|
+
if (ids.length === 0) return;
|
|
6756
|
+
try {
|
|
6757
|
+
setError(null);
|
|
6758
|
+
const updated = await post("/settings", { contextWindowOverrides: Object.fromEntries(ids.map((id) => [id, null])) });
|
|
6759
|
+
setStatus(updated);
|
|
6760
|
+
setContextDrafts(contextDraftsFor$1(updated));
|
|
6761
|
+
onModelChange?.();
|
|
6762
|
+
} catch (cause) {
|
|
6763
|
+
setError(messageOf(cause));
|
|
6764
|
+
}
|
|
6765
|
+
};
|
|
6766
|
+
/** Force one usage read through `/quota` and render the fresh status. */
|
|
6767
|
+
const handleRefreshQuota = async () => {
|
|
6768
|
+
try {
|
|
6769
|
+
setBusy("quota");
|
|
6770
|
+
setError(null);
|
|
6771
|
+
setStatus(await post("/quota"));
|
|
6772
|
+
} catch (cause) {
|
|
6773
|
+
setError(messageOf(cause));
|
|
6774
|
+
} finally {
|
|
6775
|
+
setBusy(null);
|
|
6776
|
+
}
|
|
6777
|
+
};
|
|
6778
|
+
const handleTestConnection = async () => {
|
|
6779
|
+
try {
|
|
6780
|
+
setBusy("test");
|
|
6781
|
+
setError(null);
|
|
6782
|
+
setConnectionNotice(null);
|
|
6783
|
+
const result = await post("/test");
|
|
6784
|
+
if (result.ok === true) {
|
|
6785
|
+
setConnectionNotice(result.model === void 0 || result.model === "" ? t("testSuccess") : t("testSuccessModel").replace("{model}", result.model));
|
|
6786
|
+
return;
|
|
6787
|
+
}
|
|
6788
|
+
setConnectionNotice(result.error === void 0 || result.error === "" ? t("testFailed") : `${t("testFailed")}:${result.error}`);
|
|
6789
|
+
} catch (cause) {
|
|
6790
|
+
setConnectionNotice(`${t("testFailed")}:${messageOf(cause)}`);
|
|
6791
|
+
} finally {
|
|
6792
|
+
setBusy(null);
|
|
6793
|
+
}
|
|
6794
|
+
};
|
|
6795
|
+
if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6796
|
+
className: "dsha-page",
|
|
6797
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6798
|
+
className: "dsha-empty",
|
|
6799
|
+
children: t("loading")
|
|
6800
|
+
})
|
|
6801
|
+
});
|
|
6802
|
+
const account = status?.account;
|
|
6803
|
+
const quota = status?.quota;
|
|
6804
|
+
const models = status?.models ?? [];
|
|
6805
|
+
const hours = remainingHours(account?.expiresAtMs);
|
|
6806
|
+
const storage = status?.storage;
|
|
6807
|
+
const contextModels = status?.models.filter((model) => model.enabled) ?? [];
|
|
6808
|
+
const overrideCount = Object.keys(status?.contextWindowOverrides ?? {}).length;
|
|
6809
|
+
const quotaWindows = quota?.windows ?? (quota === void 0 || quota.usedPercent === void 0 ? [] : [{
|
|
6810
|
+
key: "interval",
|
|
6811
|
+
remainingPercent: Math.max(0, 100 - quota.usedPercent),
|
|
6812
|
+
usedPercent: quota.usedPercent,
|
|
6813
|
+
...quota.resetsAtMs === void 0 ? {} : { resetsAtMs: quota.resetsAtMs }
|
|
6814
|
+
}]);
|
|
6815
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6816
|
+
className: "dsha-page",
|
|
6817
|
+
children: [
|
|
6818
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6819
|
+
className: "dsha-muted",
|
|
6820
|
+
children: t("pageDesc")
|
|
6821
|
+
}),
|
|
6822
|
+
pool !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
|
|
6823
|
+
labels: accountPoolLabelsFor(t),
|
|
6824
|
+
accounts: pool.accounts,
|
|
6825
|
+
rotationStrategy: pool.rotationStrategy,
|
|
6826
|
+
...pool.activeAccountId === void 0 ? {} : { activeAccountId: pool.activeAccountId },
|
|
6827
|
+
busy,
|
|
6828
|
+
storageValue: storageLabel(status?.storage, t),
|
|
6829
|
+
onLogin: () => void handleLogin(),
|
|
6830
|
+
onSetPrimary: (accountId) => void poolAction("set-primary", accountId),
|
|
6831
|
+
onDelete: (accountId) => void poolAction("delete", accountId),
|
|
6832
|
+
onClearCooldown: (accountId) => void poolAction("clear-cooldown", accountId),
|
|
6833
|
+
onSetStrategy: (strategy) => void poolSetStrategy(strategy)
|
|
6834
|
+
}),
|
|
6835
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
6836
|
+
className: "dsha-group",
|
|
6837
|
+
children: [
|
|
6838
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6839
|
+
className: "dsha-grouphead",
|
|
6840
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("account") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6841
|
+
className: "dsha-value",
|
|
6842
|
+
children: authenticated ? t("signedIn") : t("signedOut")
|
|
6843
|
+
})]
|
|
6844
|
+
}),
|
|
6845
|
+
authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6846
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6847
|
+
className: "dsha-row",
|
|
6848
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6849
|
+
className: "dsha-label",
|
|
6850
|
+
children: t("accountLabel")
|
|
6851
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6852
|
+
className: "dsha-value",
|
|
6853
|
+
children: account?.label !== void 0 && account.label !== "" ? account.label : t("unknown")
|
|
6854
|
+
})]
|
|
6855
|
+
}),
|
|
6856
|
+
account?.id !== void 0 && account.id !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6857
|
+
className: "dsha-row",
|
|
6858
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6859
|
+
className: "dsha-label",
|
|
6860
|
+
children: t("accountId")
|
|
6861
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6862
|
+
className: "dsha-value dshm-mono",
|
|
6863
|
+
children: account.id
|
|
6864
|
+
})]
|
|
6865
|
+
}),
|
|
6866
|
+
account?.email !== void 0 && account.email !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6867
|
+
className: "dsha-row",
|
|
6868
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6869
|
+
className: "dsha-label",
|
|
6870
|
+
children: t("email")
|
|
6871
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6872
|
+
className: "dsha-value",
|
|
6873
|
+
children: account.email
|
|
6874
|
+
})]
|
|
6875
|
+
}),
|
|
6876
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6877
|
+
className: "dsha-row",
|
|
6878
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6879
|
+
className: "dsha-label",
|
|
6880
|
+
children: t("expiresAt")
|
|
6881
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6882
|
+
className: "dsha-value",
|
|
6883
|
+
children: [formatDate$1(account?.expiresAtMs), hours === null ? ` · ${t("expiresExpired")}` : ` · ${t("expiresRemaining").replace("{hours}", hours)}`]
|
|
6884
|
+
})]
|
|
6885
|
+
})
|
|
6886
|
+
] }),
|
|
6887
|
+
status !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6888
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6889
|
+
className: "dsha-row",
|
|
6890
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6891
|
+
className: "dsha-label",
|
|
6892
|
+
children: t("region")
|
|
6893
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6894
|
+
className: "dsha-value",
|
|
6895
|
+
children: status.region === "global" ? t("regionGlobal") : t("regionCn")
|
|
6896
|
+
})]
|
|
6897
|
+
}),
|
|
6898
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6899
|
+
className: "dsha-row",
|
|
6900
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6901
|
+
className: "dsha-label",
|
|
6902
|
+
children: t("storage")
|
|
6903
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6904
|
+
className: "dsha-value",
|
|
6905
|
+
children: storageLabel(storage, t)
|
|
6906
|
+
})]
|
|
6907
|
+
}),
|
|
6908
|
+
storage?.path !== void 0 && storage.path !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6909
|
+
className: "dsha-row",
|
|
6910
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6911
|
+
className: "dsha-label",
|
|
6912
|
+
children: t("storagePath")
|
|
6913
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6914
|
+
className: "dsha-value dshm-mono",
|
|
6915
|
+
children: storage.path
|
|
6916
|
+
})]
|
|
6917
|
+
}),
|
|
6918
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6919
|
+
className: "dsha-notice",
|
|
6920
|
+
children: t("expiresHint")
|
|
6921
|
+
})
|
|
6922
|
+
] }),
|
|
6923
|
+
flow !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6924
|
+
className: "dsha-device-box",
|
|
6925
|
+
children: [
|
|
6926
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("deviceCodeSection") }),
|
|
6927
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6928
|
+
className: "dsha-muted",
|
|
6929
|
+
children: t("deviceCodeHint")
|
|
6930
|
+
}),
|
|
6931
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6932
|
+
className: "dsha-code-row",
|
|
6933
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6934
|
+
className: "dsha-code",
|
|
6935
|
+
"aria-label": t("userCode"),
|
|
6936
|
+
children: flow.userCode
|
|
6937
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6938
|
+
className: "dsha-btn",
|
|
6939
|
+
onClick: () => void handleCopyCode(),
|
|
6940
|
+
children: copied ? t("copied") : t("copyCode")
|
|
6941
|
+
})]
|
|
6942
|
+
}),
|
|
6943
|
+
flow.verificationUri !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
6944
|
+
className: "dsha-link",
|
|
6945
|
+
href: flow.verificationUri,
|
|
6946
|
+
target: "_blank",
|
|
6947
|
+
rel: "noreferrer noopener",
|
|
6948
|
+
children: flow.verificationUri
|
|
6949
|
+
}),
|
|
6950
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6951
|
+
className: "dsha-row",
|
|
6952
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6953
|
+
className: "dsha-label",
|
|
6954
|
+
children: t("codeExpires")
|
|
6955
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6956
|
+
className: "dsha-value",
|
|
6957
|
+
children: t("codeMinutes").replace("{minutes}", String(Math.max(1, Math.round(flow.expiresInSec / 60))))
|
|
6958
|
+
})]
|
|
6959
|
+
}),
|
|
6960
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6961
|
+
className: "dsha-muted",
|
|
6962
|
+
children: t("waitingAuthorization")
|
|
6963
|
+
}),
|
|
6964
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6965
|
+
className: "dsha-actions",
|
|
6966
|
+
children: [flow.verificationUri !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
6967
|
+
className: "dsha-btn",
|
|
6968
|
+
href: flow.verificationUri,
|
|
6969
|
+
target: "_blank",
|
|
6970
|
+
rel: "noreferrer noopener",
|
|
6971
|
+
children: t("openSignInPage")
|
|
6972
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6973
|
+
className: "dsha-btn",
|
|
6974
|
+
onClick: () => void handleCancelLogin(),
|
|
6975
|
+
children: t("cancelSignIn")
|
|
6976
|
+
})]
|
|
6977
|
+
})
|
|
6978
|
+
]
|
|
6979
|
+
}),
|
|
6980
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6981
|
+
className: "dsha-actions",
|
|
6982
|
+
children: [flow === null && !authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6983
|
+
className: "dsha-btn dsha-btn-primary",
|
|
6984
|
+
disabled: busy !== null,
|
|
6985
|
+
onClick: () => void handleLogin(),
|
|
6986
|
+
children: busy === "login" ? t("signingIn") : t("signIn")
|
|
6987
|
+
}), flow === null && authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6988
|
+
className: "dsha-btn",
|
|
6989
|
+
disabled: busy !== null || status?.ownedByPlugin === false,
|
|
6990
|
+
title: status?.ownedByPlugin === false ? t("logoutOwnedByApp") : void 0,
|
|
6991
|
+
onClick: () => void handleLogout(),
|
|
6992
|
+
children: t("signOut")
|
|
6993
|
+
})]
|
|
6994
|
+
}),
|
|
6995
|
+
flow === null && authenticated && status?.ownedByPlugin === false && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6996
|
+
className: "dsha-muted",
|
|
6997
|
+
children: t("logoutOwnedByApp")
|
|
6998
|
+
})
|
|
6999
|
+
]
|
|
7000
|
+
}),
|
|
7001
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
7002
|
+
className: "dsha-group",
|
|
7003
|
+
children: [
|
|
7004
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7005
|
+
className: "dsha-grouphead",
|
|
7006
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("connection") })
|
|
7007
|
+
}),
|
|
7008
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7009
|
+
className: "dsha-row",
|
|
7010
|
+
style: { marginBottom: 12 },
|
|
7011
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7012
|
+
className: "dsha-label",
|
|
7013
|
+
style: { fontWeight: 600 },
|
|
7014
|
+
children: t("enableProvider")
|
|
7015
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
7016
|
+
type: "checkbox",
|
|
7017
|
+
"aria-label": t("enableProvider"),
|
|
7018
|
+
checked: status?.enabled !== false,
|
|
7019
|
+
disabled: busy !== null,
|
|
7020
|
+
onChange: (event) => void toggleEnabled(event.currentTarget.checked)
|
|
7021
|
+
})]
|
|
7022
|
+
}),
|
|
7023
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7024
|
+
className: "dsha-row",
|
|
7025
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7026
|
+
className: "dsha-label",
|
|
7027
|
+
children: t("provider")
|
|
7028
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7029
|
+
className: "dsha-value",
|
|
7030
|
+
children: `${MINIMAX_CODE_PROVIDER_NAME} · ${MINIMAX_CODE_PROVIDER_ID}`
|
|
7031
|
+
})]
|
|
7032
|
+
}),
|
|
7033
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7034
|
+
className: "dsha-row",
|
|
7035
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7036
|
+
className: "dsha-label",
|
|
7037
|
+
children: t("connectionState")
|
|
7038
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7039
|
+
className: "dsha-value",
|
|
7040
|
+
children: authenticated ? t("connected") : t("untested")
|
|
7041
|
+
})]
|
|
7042
|
+
}),
|
|
7043
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7044
|
+
className: "dsha-notice",
|
|
7045
|
+
children: status?.serving === false && status.conflict ? t("routeConflict").replace("{detail}", status.conflict) : t("routeOwned")
|
|
7046
|
+
}),
|
|
7047
|
+
connectionNotice !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7048
|
+
className: "dsha-muted",
|
|
7049
|
+
children: connectionNotice
|
|
7050
|
+
}),
|
|
7051
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7052
|
+
className: "dsha-actions",
|
|
7053
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7054
|
+
className: "dsha-btn",
|
|
7055
|
+
disabled: busy !== null || !authenticated,
|
|
7056
|
+
onClick: () => void handleTestConnection(),
|
|
7057
|
+
children: busy === "test" ? t("testingConnection") : t("testConnection")
|
|
7058
|
+
})
|
|
7059
|
+
})
|
|
7060
|
+
]
|
|
7061
|
+
}),
|
|
7062
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
7063
|
+
className: "dsha-group",
|
|
7064
|
+
children: [
|
|
7065
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7066
|
+
className: "dsha-grouphead",
|
|
7067
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("modelsSection") })
|
|
7068
|
+
}),
|
|
7069
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7070
|
+
className: "dsha-muted",
|
|
7071
|
+
children: t("modelsHint").replace("{count}", String(models.length))
|
|
7072
|
+
}),
|
|
7073
|
+
models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7074
|
+
className: "dsha-empty",
|
|
7075
|
+
children: t("modelsUnavailable")
|
|
7076
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7077
|
+
className: "dsha-models",
|
|
7078
|
+
"aria-label": t("modelsSection"),
|
|
7079
|
+
children: models.map((model) => {
|
|
7080
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
7081
|
+
title: [
|
|
7082
|
+
model.id,
|
|
7083
|
+
thinkingLabel(model.thinking, t),
|
|
7084
|
+
...model.description === null || model.description === "" ? [] : [model.description]
|
|
7085
|
+
].join(" · "),
|
|
7086
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
7087
|
+
type: "checkbox",
|
|
7088
|
+
checked: model.enabled,
|
|
7089
|
+
disabled: busy !== null,
|
|
7090
|
+
onChange: (event) => toggleModel(model.id, event.currentTarget.checked)
|
|
7091
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name })]
|
|
7092
|
+
}, model.id);
|
|
7093
|
+
})
|
|
7094
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7095
|
+
className: "dsha-actions",
|
|
7096
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7097
|
+
className: "dsha-btn",
|
|
7098
|
+
disabled: busy !== null,
|
|
7099
|
+
onClick: () => setAllModels(true),
|
|
7100
|
+
children: t("selectAll")
|
|
7101
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7102
|
+
className: "dsha-btn",
|
|
7103
|
+
disabled: busy !== null,
|
|
7104
|
+
onClick: () => setAllModels(false),
|
|
7105
|
+
children: t("unselectAll")
|
|
7106
|
+
})]
|
|
7107
|
+
})] })
|
|
7108
|
+
]
|
|
7109
|
+
}),
|
|
7110
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
7111
|
+
className: "dsha-group",
|
|
7112
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7113
|
+
className: "dsha-grouphead",
|
|
7114
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("enhanced") })
|
|
7115
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7116
|
+
className: "dsha-pref-row",
|
|
7117
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("defaultReasoningEffort") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7118
|
+
className: "dsha-muted",
|
|
7119
|
+
children: t("defaultReasoningEffortHint")
|
|
7120
|
+
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
7121
|
+
className: "dsha-select",
|
|
7122
|
+
"aria-label": t("defaultReasoningEffort"),
|
|
7123
|
+
value: status?.defaultReasoningEffort ?? "",
|
|
7124
|
+
disabled: busy !== null,
|
|
7125
|
+
onChange: (event) => {
|
|
7126
|
+
const value = event.currentTarget.value;
|
|
7127
|
+
handleUpdateEffort(value === "" ? null : value);
|
|
7128
|
+
},
|
|
7129
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7130
|
+
value: "",
|
|
7131
|
+
children: t("defaultEffortAuto")
|
|
7132
|
+
}), MINIMAX_CODE_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
7133
|
+
value: effort,
|
|
7134
|
+
children: effort
|
|
7135
|
+
}, effort))]
|
|
7136
|
+
})]
|
|
7137
|
+
})]
|
|
7138
|
+
}),
|
|
7139
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
7140
|
+
className: "dsha-group",
|
|
7141
|
+
children: [
|
|
7142
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7143
|
+
className: "dsha-grouphead",
|
|
7144
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("contextWindowSection") })
|
|
7145
|
+
}),
|
|
7146
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7147
|
+
className: "dsha-muted",
|
|
7148
|
+
children: t("contextWindowHint")
|
|
7149
|
+
}),
|
|
7150
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7151
|
+
className: "dsha-context-settings",
|
|
7152
|
+
children: [
|
|
7153
|
+
contextModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7154
|
+
className: "dsha-muted",
|
|
7155
|
+
children: t("contextWindowNoneEnabled")
|
|
7156
|
+
}),
|
|
7157
|
+
contextModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7158
|
+
className: "dsha-context-row",
|
|
7159
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7160
|
+
title: model.id,
|
|
7161
|
+
children: [model.name, model.defaultContextWindow < model.contextWindow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7162
|
+
className: "dsha-model-meta",
|
|
7163
|
+
children: formatCapacity$1(model.contextWindow)
|
|
7164
|
+
})]
|
|
7165
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7166
|
+
className: "dsha-capacity-control",
|
|
7167
|
+
children: [
|
|
7168
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
7169
|
+
type: "text",
|
|
7170
|
+
"aria-label": model.name + " " + t("contextWindowSection"),
|
|
7171
|
+
value: contextDrafts[model.id] ?? "",
|
|
7172
|
+
onChange: (event) => setContextDrafts({
|
|
7173
|
+
...contextDrafts,
|
|
7174
|
+
[model.id]: event.currentTarget.value
|
|
7175
|
+
}),
|
|
7176
|
+
onKeyDown: (event) => {
|
|
7177
|
+
if (event.key === "Enter") handleSaveContextWindow(model.id);
|
|
7178
|
+
}
|
|
7179
|
+
}),
|
|
7180
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
|
|
7181
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7182
|
+
type: "button",
|
|
7183
|
+
className: "dsha-context-save",
|
|
7184
|
+
disabled: savingModel === model.id,
|
|
7185
|
+
onClick: () => void handleSaveContextWindow(model.id),
|
|
7186
|
+
children: savingModel === model.id ? t("saving") : t("save")
|
|
7187
|
+
}),
|
|
7188
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7189
|
+
type: "button",
|
|
7190
|
+
className: "dsha-context-save dsha-context-reset",
|
|
7191
|
+
"aria-label": model.name + " " + t("contextWindowReset"),
|
|
7192
|
+
disabled: savingModel === model.id || status?.contextWindowOverrides[model.id] === void 0,
|
|
7193
|
+
onClick: () => void handleResetContextWindow(model.id),
|
|
7194
|
+
children: t("contextWindowReset")
|
|
7195
|
+
})
|
|
7196
|
+
]
|
|
7197
|
+
})]
|
|
7198
|
+
}, model.id)),
|
|
7199
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7200
|
+
className: "dsha-actions",
|
|
7201
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7202
|
+
className: "dsha-btn",
|
|
7203
|
+
disabled: busy !== null || overrideCount === 0,
|
|
7204
|
+
onClick: () => void handleResetAllContextWindows(),
|
|
7205
|
+
children: t("contextWindowResetAll")
|
|
7206
|
+
})
|
|
7207
|
+
})
|
|
7208
|
+
]
|
|
7209
|
+
})
|
|
7210
|
+
]
|
|
7211
|
+
}),
|
|
7212
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
7213
|
+
className: "dsha-group",
|
|
7214
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7215
|
+
className: "dsha-grouphead",
|
|
7216
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("quotaSection") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7217
|
+
className: "dsha-btn",
|
|
7218
|
+
disabled: busy !== null || !authenticated,
|
|
7219
|
+
onClick: () => void handleRefreshQuota(),
|
|
7220
|
+
children: busy === "quota" ? t("quotaRefreshing") : t("quotaRefresh")
|
|
7221
|
+
})]
|
|
7222
|
+
}), quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7223
|
+
className: "dsha-notice dshm-quota-note",
|
|
7224
|
+
children: status?.quotaUnavailable === "credential-not-accepted" ? t("quotaNeedsApiKey") : status?.quotaUnavailable === "unreachable" ? t("quotaUnreachable") : t("quotaUnavailable")
|
|
7225
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7226
|
+
className: "dsha-quota-card",
|
|
7227
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7228
|
+
className: "dsha-quota-title",
|
|
7229
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota.label }), quota.usedPercent !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quotaUsed").replace("{percent}", String(Math.round(quota.usedPercent))) })]
|
|
7230
|
+
}), quotaWindows.map((window) => {
|
|
7231
|
+
const remaining = window.remainingPercent;
|
|
7232
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7233
|
+
className: "dsha-meter-wrap",
|
|
7234
|
+
children: [
|
|
7235
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7236
|
+
className: "dsha-meter-label",
|
|
7237
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window.key === "weekly" ? t("quotaWindowWeekly") : t("quotaWindowInterval") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: window.unlimited === true ? t("quotaUnlimited") : remaining === null ? t("unknown") : t("quotaRemaining").replace("{percent}", String(Math.max(0, Math.round(remaining)))) })]
|
|
7238
|
+
}),
|
|
7239
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7240
|
+
className: `dsha-meter ${(remaining ?? 100) <= 10 ? "dsha-meter-cyan" : "dsha-meter-green"}`,
|
|
7241
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${Math.min(100, Math.max(0, Math.round(remaining ?? 100)))}%` } })
|
|
7242
|
+
}),
|
|
7243
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7244
|
+
className: "dsha-meter-meta",
|
|
7245
|
+
children: [window.used !== void 0 && window.total !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quotaCounts").replace("{used}", window.used.toLocaleString()).replace("{total}", window.total.toLocaleString()) }), window.resetsAtMs !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quotaReset").replace("{time}", formatDate$1(window.resetsAtMs)) })]
|
|
7246
|
+
})
|
|
7247
|
+
]
|
|
7248
|
+
}, window.key);
|
|
7249
|
+
})]
|
|
7250
|
+
})]
|
|
7251
|
+
}),
|
|
7252
|
+
error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7253
|
+
className: "dsha-error",
|
|
7254
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: error })
|
|
7255
|
+
})
|
|
7256
|
+
]
|
|
7257
|
+
});
|
|
7258
|
+
}
|
|
7259
|
+
//#endregion
|
|
7260
|
+
//#region src/shared/workbuddy-contracts.ts
|
|
7261
|
+
/** Every level this route can name, in escalating order (the card's sort key). */
|
|
7262
|
+
const WORKBUDDY_REASONING_EFFORTS = [
|
|
7263
|
+
"minimal",
|
|
7264
|
+
"low",
|
|
7265
|
+
"medium",
|
|
7266
|
+
"high",
|
|
7267
|
+
"xhigh",
|
|
7268
|
+
"max"
|
|
7269
|
+
];
|
|
7270
|
+
//#endregion
|
|
7271
|
+
//#region src/client/workbuddy/locales.ts
|
|
7272
|
+
const NS_WORKBUDDY = "dsh-workbuddy";
|
|
7273
|
+
const zh$1 = {
|
|
7274
|
+
title: "WorkBuddy",
|
|
7275
|
+
pageDesc: "复用本机 CodeBuddy 桌面端登录态,管理 WorkBuddy(CodeBuddy 订阅)模型、上下文窗口与额度。",
|
|
7276
|
+
account: "账号",
|
|
7277
|
+
noAccounts: "暂无账号。点击右上角「添加账号」完成浏览器授权,或登录 CodeBuddy 桌面端后重新扫描;桌面账号只能从本插件隐藏,绝不删除 CodeBuddy 的原凭据。",
|
|
7278
|
+
signedOut: "未找到凭据",
|
|
7279
|
+
nickname: "昵称",
|
|
7280
|
+
uin: "UIN",
|
|
7281
|
+
region: "区域",
|
|
7282
|
+
regionCn: "国区",
|
|
7283
|
+
regionIntl: "国际区",
|
|
7284
|
+
accountType: "账号类型",
|
|
7285
|
+
sourceFile: "凭据文件",
|
|
7286
|
+
authDirectory: "凭据目录",
|
|
7287
|
+
storage: "凭据存储",
|
|
7288
|
+
storageNotice: "桌面端账号仍读取 CodeBuddy 自己的凭据文件,插件不会删除这些文件;通过这里添加的账号保存在系统加密存储中(Windows DPAPI / macOS Keychain / Linux Secret Service),token 不进入浏览器。",
|
|
7289
|
+
routeUnreachable: "无法读取 WorkBuddy 设置路由",
|
|
7290
|
+
routeUnreachableHint: "浏览器里加载的插件版本可能比 Host 进程里运行的新(客户端资源是现读磁盘的,Host 只在启动时加载)。请重启 DSH,让两端来自同一份构建。",
|
|
7291
|
+
rescan: "重新扫描",
|
|
7292
|
+
rescanning: "扫描中...",
|
|
7293
|
+
accounts: "账号管理",
|
|
7294
|
+
addCnAccount: "添加国区账号",
|
|
7295
|
+
addIntlAccount: "添加国际区账号",
|
|
7296
|
+
authorizing: "授权中…",
|
|
7297
|
+
loginWaiting: "请在新打开的浏览器页面完成登录与授权。",
|
|
7298
|
+
loginFailed: "账号授权失败",
|
|
7299
|
+
encryptedStorage: "系统加密存储",
|
|
7300
|
+
hiddenAccount: "已隐藏",
|
|
7301
|
+
hideAccount: "从插件隐藏",
|
|
7302
|
+
restoreAccount: "恢复显示",
|
|
7303
|
+
deleteAccount: "删除账号",
|
|
7304
|
+
deleteConfirm: "确定删除这个插件托管的账号吗?加密存储中的登录凭据会被移除。",
|
|
7305
|
+
connection: "连接",
|
|
7306
|
+
provider: "Provider",
|
|
7307
|
+
providerValue: "WorkBuddy Subscription · workbuddy-subscription",
|
|
7308
|
+
connectionState: "连接状态",
|
|
7309
|
+
connected: "已连接",
|
|
7310
|
+
untested: "未测试",
|
|
7311
|
+
testConnection: "测试连接",
|
|
7312
|
+
testingConnection: "测试中...",
|
|
7313
|
+
latency: "延迟",
|
|
7314
|
+
routeOwned: "模型路由由本插件提供",
|
|
7315
|
+
routeConflict: "模型路由已被其他 Provider 占用:{detail}。请在 DSH 设置中移除重复的 Provider 配置后重试。",
|
|
7316
|
+
modelsSection: "模型",
|
|
7317
|
+
enableProvider: "启用此供应商",
|
|
7318
|
+
modelsHint: "勾选后模型才会出现在对话页的模型选择列表中;未勾选或关闭上方开关可在列表中隐藏该供应商。目录与上下文窗口来自订阅网关的模型目录,并按账号所在区域过滤——跨区调用会被上游拒绝。",
|
|
7319
|
+
refreshCatalog: "刷新模型目录",
|
|
7320
|
+
refreshingCatalog: "刷新中...",
|
|
6137
7321
|
selectAll: "全选",
|
|
6138
7322
|
unselectAll: "全不选",
|
|
6139
7323
|
imageSupport: "图片",
|
|
@@ -7327,6 +8511,10 @@ window.__ModuleLoader__.load({
|
|
|
7327
8511
|
id: "workbuddy",
|
|
7328
8512
|
label: "WorkBuddy"
|
|
7329
8513
|
},
|
|
8514
|
+
{
|
|
8515
|
+
id: "minimax-code",
|
|
8516
|
+
label: "MiniMax Code"
|
|
8517
|
+
},
|
|
7330
8518
|
{
|
|
7331
8519
|
id: "claude",
|
|
7332
8520
|
label: "Claude"
|
|
@@ -7341,6 +8529,31 @@ window.__ModuleLoader__.load({
|
|
|
7341
8529
|
*/
|
|
7342
8530
|
function ProviderHubSection({ t, onModelChange, ...runtime }) {
|
|
7343
8531
|
const [active, setActive] = (0, react.useState)("chatgpt");
|
|
8532
|
+
const tabStripRef = (0, react.useRef)(null);
|
|
8533
|
+
/**
|
|
8534
|
+
* Keep the selected tab inside the visible strip.
|
|
8535
|
+
*
|
|
8536
|
+
* The strip is one scrolling line, so a tab selected by keyboard (or restored
|
|
8537
|
+
* after a remount) can sit outside the viewport with no feedback about where
|
|
8538
|
+
* the selection went. `scrollIntoView` with `inline: 'nearest'` scrolls only
|
|
8539
|
+
* when the tab is actually out of view and keeps the change to the horizontal
|
|
8540
|
+
* axis, so it never nudges the settings page vertically.
|
|
8541
|
+
*
|
|
8542
|
+
* Guarded because jsdom (the DOM these tests run against) does not implement
|
|
8543
|
+
* `scrollIntoView`, and a settings page must not break in an environment that
|
|
8544
|
+
* lacks a scrolling method.
|
|
8545
|
+
*/
|
|
8546
|
+
(0, react.useEffect)(() => {
|
|
8547
|
+
const strip = tabStripRef.current;
|
|
8548
|
+
if (strip === null) return;
|
|
8549
|
+
const selected = strip.querySelector("[role=\"tab\"][aria-selected=\"true\"]");
|
|
8550
|
+
if (selected === null) return;
|
|
8551
|
+
if (typeof selected.scrollIntoView !== "function") return;
|
|
8552
|
+
selected.scrollIntoView({
|
|
8553
|
+
inline: "nearest",
|
|
8554
|
+
block: "nearest"
|
|
8555
|
+
});
|
|
8556
|
+
}, [active]);
|
|
7344
8557
|
const onTabKeyDown = (0, react.useCallback)((event) => {
|
|
7345
8558
|
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
7346
8559
|
event.preventDefault();
|
|
@@ -7360,6 +8573,7 @@ window.__ModuleLoader__.load({
|
|
|
7360
8573
|
children: t("hubTitle")
|
|
7361
8574
|
}) }),
|
|
7362
8575
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8576
|
+
ref: tabStripRef,
|
|
7363
8577
|
className: "dsh-codex-segments dsh-hub-tabs",
|
|
7364
8578
|
role: "tablist",
|
|
7365
8579
|
"aria-label": t("hubTitle"),
|
|
@@ -7389,6 +8603,7 @@ window.__ModuleLoader__.load({
|
|
|
7389
8603
|
active === "command-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CommandCodeSection, { onModelChange }) : null,
|
|
7390
8604
|
active === "kimi-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KimiCodeSection, { onModelChange }) : null,
|
|
7391
8605
|
active === "workbuddy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkBuddySection, { onModelChange }) : null,
|
|
8606
|
+
active === "minimax-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MinimaxCodeSection, { onModelChange }) : null,
|
|
7392
8607
|
active === "claude" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClaudeSection, { onModelChange }) : null
|
|
7393
8608
|
]
|
|
7394
8609
|
})
|
|
@@ -7668,7 +8883,8 @@ window.__ModuleLoader__.load({
|
|
|
7668
8883
|
};
|
|
7669
8884
|
//#endregion
|
|
7670
8885
|
//#region src/client/styles.ts
|
|
7671
|
-
const
|
|
8886
|
+
const PLUGIN_ID = "@eddyskywalker/dsh-chatgpt-subscription";
|
|
8887
|
+
const STYLE_ID$5 = `${PLUGIN_ID}/main`;
|
|
7672
8888
|
const CSS = `
|
|
7673
8889
|
.dsh-codex-page{box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:20px;max-width:780px;min-width:0;padding:2px 0 30px}
|
|
7674
8890
|
.dsh-codex-page *{box-sizing:border-box}
|
|
@@ -7771,27 +8987,73 @@ window.__ModuleLoader__.load({
|
|
|
7771
8987
|
.dsh-codex-image-preview{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:8px;display:block;max-height:260px;max-width:min(100%,360px);object-fit:contain}
|
|
7772
8988
|
.dsh-codex-image-loading,.dsh-codex-image-failed{border:0.5px dashed var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-tertiary);display:inline-flex;font-size:12px;line-height:1.4;padding:18px 20px}
|
|
7773
8989
|
.dsh-codex-image-failed{color:var(--dsw-alias-label-danger,#d94b4b)}
|
|
7774
|
-
.
|
|
8990
|
+
/* Seven provider tabs overflow a narrow settings pane. The shared
|
|
8991
|
+
.dsh-codex-segments rule pins flex-wrap to nowrap, so the strip originally ran
|
|
8992
|
+
past the pane edge with no way to reach the trailing tabs. Wrapping restored
|
|
8993
|
+
reachability but produced a ragged second row (five tabs, then two) whose right
|
|
8994
|
+
edge bore no relation to the first row's, which reads as a layout accident
|
|
8995
|
+
rather than a deliberate two-row control. The strip therefore stays on ONE line
|
|
8996
|
+
and scrolls horizontally.
|
|
8997
|
+
The scrollbar is deliberately thin but VISIBLE: it is the affordance that says
|
|
8998
|
+
more tabs exist, and hiding it would strand a mouse user, whose vertical wheel
|
|
8999
|
+
cannot scroll this row — the original bug in a new shape.
|
|
9000
|
+
Buttons are flex:none so the row scrolls instead of squashing labels. The
|
|
9001
|
+
padding is 4px, not the shared 3px, because overflow clips at the padding box:
|
|
9002
|
+
the focus ring is 2px wide with a 2px offset (4px beyond the button), so 3px
|
|
9003
|
+
would shave a pixel off it for keyboard users. scroll-padding keeps the same
|
|
9004
|
+
margin when a tab is scrolled into view by focus or by the active-tab effect
|
|
9005
|
+
in ProviderHubSection.
|
|
9006
|
+
Scoped to .dsh-hub-tabs so the ChatGPT provider-search group, which reuses
|
|
9007
|
+
.dsh-codex-segments, keeps its single-line layout. */
|
|
9008
|
+
.dsh-hub-tabs{align-self:flex-start;flex-wrap:nowrap;max-width:100%;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;padding:4px;scroll-padding-inline:4px;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l2) transparent}
|
|
9009
|
+
.dsh-hub-tabs button{flex:none}
|
|
9010
|
+
.dsh-hub-tabs::-webkit-scrollbar{height:6px}
|
|
9011
|
+
.dsh-hub-tabs::-webkit-scrollbar-track{background:transparent}
|
|
9012
|
+
.dsh-hub-tabs::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l2);border-radius:999px}
|
|
7775
9013
|
@keyframes dsh-codex-pulse{0%,100%{opacity:.45}50%{opacity:.85}}
|
|
7776
9014
|
@media(max-width:560px){.dsh-codex-row,.dsh-codex-pref-row,.dsh-codex-quota-fact,.dsh-codex-reset-credits{align-items:flex-start;flex-direction:column;gap:3px}.dsh-codex-value,.dsh-codex-quota-fact strong{text-align:left}.dsh-codex-actions{justify-content:flex-start}.dsh-codex-grouphead{align-items:flex-start;flex-direction:column;gap:0;padding:12px 0}.dsh-codex-meter-meta{align-items:flex-start;flex-direction:column;gap:2px}.dsh-codex-errorbar{align-items:flex-start;flex-direction:column}.dsh-codex-segments{width:100%}.dsh-codex-select{max-width:none;width:100%}.dsh-codex-context-row{align-items:flex-start;flex-direction:column;gap:5px}.dsh-codex-segments label{flex:1}.dsh-codex-segments span{text-align:center}.dsh-codex-image-tool{max-width:100%;margin-left:0}}
|
|
7777
9015
|
@media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}
|
|
7778
9016
|
`;
|
|
9017
|
+
/**
|
|
9018
|
+
* Install the ChatGPT tab's stylesheet as a document-owned, never-removed
|
|
9019
|
+
* `<style>` element.
|
|
9020
|
+
*
|
|
9021
|
+
* The other client stylesheets this plugin installs are additive: their
|
|
9022
|
+
* installers no-op when the element already exists and their disposers do
|
|
9023
|
+
* nothing, so a restart can never take the styles away. This one used to
|
|
9024
|
+
* create *and remove* its element, and the dedupe handoff was racy: on a
|
|
9025
|
+
* plugin fiber restart (config change, dependency reload, HMR) the new fiber
|
|
9026
|
+
* ran `apply()` before the old fiber's async unload removed the element —
|
|
9027
|
+
* dedupe saw the old tag, returned a no-op disposer, and the old unload then
|
|
9028
|
+
* deleted the only copy. Every later restart kept returning the no-op, so the
|
|
9029
|
+
* stylesheet never came back and the settings page rendered unstyled.
|
|
9030
|
+
*
|
|
9031
|
+
* Fix: treat the tag as owned by the document rather than by one fiber —
|
|
9032
|
+
* create it when missing, refresh `textContent` when a rebuilt bundle ships
|
|
9033
|
+
* different CSS (HMR), and return a no-op disposer unconditionally, matching
|
|
9034
|
+
* the additive installers.
|
|
9035
|
+
*/
|
|
7779
9036
|
function installStyles() {
|
|
7780
|
-
if (document
|
|
9037
|
+
if (typeof document === "undefined") return () => void 0;
|
|
9038
|
+
const existing = document.querySelector(`style[data-plugin-css="${STYLE_ID$5}"]`);
|
|
9039
|
+
if (existing !== null) {
|
|
9040
|
+
if (existing.textContent !== CSS) existing.textContent = CSS;
|
|
9041
|
+
return () => void 0;
|
|
9042
|
+
}
|
|
7781
9043
|
const element = document.createElement("style");
|
|
7782
|
-
element.dataset.plugin =
|
|
7783
|
-
element.dataset.pluginCss = STYLE_ID$
|
|
9044
|
+
element.dataset.plugin = PLUGIN_ID;
|
|
9045
|
+
element.dataset.pluginCss = STYLE_ID$5;
|
|
7784
9046
|
element.textContent = CSS;
|
|
7785
9047
|
document.head.appendChild(element);
|
|
7786
|
-
return () =>
|
|
9048
|
+
return () => void 0;
|
|
7787
9049
|
}
|
|
7788
9050
|
//#endregion
|
|
7789
9051
|
//#region src/client/antigravity/styles.ts
|
|
7790
|
-
const STYLE_ID$
|
|
9052
|
+
const STYLE_ID$4 = "dsh-antigravity-settings-style";
|
|
7791
9053
|
function installAntigravityStyles() {
|
|
7792
9054
|
if (typeof document === "undefined" || document.getElementById("dsh-antigravity-settings-style")) return;
|
|
7793
9055
|
const style = document.createElement("style");
|
|
7794
|
-
style.id = STYLE_ID$
|
|
9056
|
+
style.id = STYLE_ID$4;
|
|
7795
9057
|
style.textContent = `
|
|
7796
9058
|
.dsha-page{box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:20px;max-width:780px;min-width:0;padding:2px 0 30px}
|
|
7797
9059
|
.dsha-page *{box-sizing:border-box}
|
|
@@ -7935,7 +9197,7 @@ window.__ModuleLoader__.load({
|
|
|
7935
9197
|
}
|
|
7936
9198
|
}
|
|
7937
9199
|
function AntigravityComposerQuota({ directory, loadModelDirectory }) {
|
|
7938
|
-
const modelState = useStore$
|
|
9200
|
+
const modelState = useStore$5(directory);
|
|
7939
9201
|
const [status, setStatus] = (0, react.useState)(null);
|
|
7940
9202
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
7941
9203
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -7992,7 +9254,7 @@ window.__ModuleLoader__.load({
|
|
|
7992
9254
|
})]
|
|
7993
9255
|
});
|
|
7994
9256
|
}
|
|
7995
|
-
function useStore$
|
|
9257
|
+
function useStore$5(store) {
|
|
7996
9258
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
7997
9259
|
}
|
|
7998
9260
|
//#endregion
|
|
@@ -8025,7 +9287,7 @@ window.__ModuleLoader__.load({
|
|
|
8025
9287
|
* remaining is 100 - used. A window at 0% used is the normal empty state and
|
|
8026
9288
|
* grades as 'normal', not as an error.
|
|
8027
9289
|
*/
|
|
8028
|
-
function selectBadgeFacts$
|
|
9290
|
+
function selectBadgeFacts$4(status) {
|
|
8029
9291
|
const quota = status?.quota;
|
|
8030
9292
|
if (quota === null || quota === void 0) return {
|
|
8031
9293
|
text: "—",
|
|
@@ -8054,7 +9316,7 @@ window.__ModuleLoader__.load({
|
|
|
8054
9316
|
};
|
|
8055
9317
|
}
|
|
8056
9318
|
function ClaudeComposerQuota({ directory, loadModelDirectory }) {
|
|
8057
|
-
const modelState = useStore$
|
|
9319
|
+
const modelState = useStore$4(directory);
|
|
8058
9320
|
const [status, setStatus] = (0, react.useState)(null);
|
|
8059
9321
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
8060
9322
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -8088,7 +9350,7 @@ window.__ModuleLoader__.load({
|
|
|
8088
9350
|
window.clearInterval(timer);
|
|
8089
9351
|
};
|
|
8090
9352
|
}, [fetchStatus, isClaude]);
|
|
8091
|
-
const facts = (0, react.useMemo)(() => selectBadgeFacts$
|
|
9353
|
+
const facts = (0, react.useMemo)(() => selectBadgeFacts$4(status), [status]);
|
|
8092
9354
|
if (!isClaude || !status?.authenticated || facts === null) return null;
|
|
8093
9355
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8094
9356
|
className: "dsha-composer-quota",
|
|
@@ -8105,12 +9367,12 @@ window.__ModuleLoader__.load({
|
|
|
8105
9367
|
})]
|
|
8106
9368
|
});
|
|
8107
9369
|
}
|
|
8108
|
-
function useStore$
|
|
9370
|
+
function useStore$4(store) {
|
|
8109
9371
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
8110
9372
|
}
|
|
8111
9373
|
//#endregion
|
|
8112
9374
|
//#region src/client/claude/styles.ts
|
|
8113
|
-
const STYLE_ID$
|
|
9375
|
+
const STYLE_ID$3 = "dsh-claude-settings-style";
|
|
8114
9376
|
/**
|
|
8115
9377
|
* Claude-only additions to the shared settings design system.
|
|
8116
9378
|
*
|
|
@@ -8126,7 +9388,7 @@ window.__ModuleLoader__.load({
|
|
|
8126
9388
|
function installClaudeStyles() {
|
|
8127
9389
|
if (typeof document === "undefined" || document.getElementById("dsh-claude-settings-style")) return;
|
|
8128
9390
|
const style = document.createElement("style");
|
|
8129
|
-
style.id = STYLE_ID$
|
|
9391
|
+
style.id = STYLE_ID$3;
|
|
8130
9392
|
style.textContent = `
|
|
8131
9393
|
.dsha-badge.claude-adopted{background:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 16%,var(--dsw-alias-bg-layer-1));border-color:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 45%,var(--dsw-alias-border-l2));color:var(--dsw-alias-label-primary)}
|
|
8132
9394
|
.dshcl-flow{border-bottom:0.5px solid var(--dsw-alias-border-l2);display:flex;flex-direction:column;gap:10px;padding:12px 0}
|
|
@@ -8161,7 +9423,7 @@ window.__ModuleLoader__.load({
|
|
|
8161
9423
|
* A bounded usage window is the number a user actually spends down, so it wins
|
|
8162
9424
|
* over a credit balance; the balance shows only when no window is reported.
|
|
8163
9425
|
*/
|
|
8164
|
-
function selectBadgeFacts$
|
|
9426
|
+
function selectBadgeFacts$3(status) {
|
|
8165
9427
|
const quota = status?.quota;
|
|
8166
9428
|
if (quota === null || quota === void 0) return {
|
|
8167
9429
|
text: "—",
|
|
@@ -8203,7 +9465,7 @@ window.__ModuleLoader__.load({
|
|
|
8203
9465
|
};
|
|
8204
9466
|
}
|
|
8205
9467
|
function CommandCodeComposerQuota({ directory, loadModelDirectory }) {
|
|
8206
|
-
const modelState = useStore$
|
|
9468
|
+
const modelState = useStore$3(directory);
|
|
8207
9469
|
const [status, setStatus] = (0, react.useState)(null);
|
|
8208
9470
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
8209
9471
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -8237,7 +9499,7 @@ window.__ModuleLoader__.load({
|
|
|
8237
9499
|
window.clearInterval(timer);
|
|
8238
9500
|
};
|
|
8239
9501
|
}, [fetchStatus, isCommandCode]);
|
|
8240
|
-
const facts = (0, react.useMemo)(() => selectBadgeFacts$
|
|
9502
|
+
const facts = (0, react.useMemo)(() => selectBadgeFacts$3(status), [status]);
|
|
8241
9503
|
if (!isCommandCode || !status?.authenticated || facts === null) return null;
|
|
8242
9504
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8243
9505
|
className: "dsha-composer-quota",
|
|
@@ -8254,7 +9516,7 @@ window.__ModuleLoader__.load({
|
|
|
8254
9516
|
})]
|
|
8255
9517
|
});
|
|
8256
9518
|
}
|
|
8257
|
-
function useStore$
|
|
9519
|
+
function useStore$3(store) {
|
|
8258
9520
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
8259
9521
|
}
|
|
8260
9522
|
//#endregion
|
|
@@ -8279,7 +9541,7 @@ window.__ModuleLoader__.load({
|
|
|
8279
9541
|
* blocks work soonest, so it wins over the longer pools; the 7-day allowance
|
|
8280
9542
|
* shows only when no 5-hour window is reported.
|
|
8281
9543
|
*/
|
|
8282
|
-
function selectBadgeFacts$
|
|
9544
|
+
function selectBadgeFacts$2(status) {
|
|
8283
9545
|
const quota = status?.quota;
|
|
8284
9546
|
if (quota === null || quota === void 0) return {
|
|
8285
9547
|
text: "—",
|
|
@@ -8311,7 +9573,7 @@ window.__ModuleLoader__.load({
|
|
|
8311
9573
|
};
|
|
8312
9574
|
}
|
|
8313
9575
|
function KimiCodeComposerQuota({ directory, loadModelDirectory }) {
|
|
8314
|
-
const modelState = useStore$
|
|
9576
|
+
const modelState = useStore$2(directory);
|
|
8315
9577
|
const [status, setStatus] = (0, react.useState)(null);
|
|
8316
9578
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
8317
9579
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -8345,7 +9607,7 @@ window.__ModuleLoader__.load({
|
|
|
8345
9607
|
window.clearInterval(timer);
|
|
8346
9608
|
};
|
|
8347
9609
|
}, [fetchStatus, isKimiCode]);
|
|
8348
|
-
const facts = (0, react.useMemo)(() => selectBadgeFacts$
|
|
9610
|
+
const facts = (0, react.useMemo)(() => selectBadgeFacts$2(status), [status]);
|
|
8349
9611
|
if (!isKimiCode || !status?.authenticated || facts === null) return null;
|
|
8350
9612
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8351
9613
|
className: "dsha-composer-quota",
|
|
@@ -8362,12 +9624,12 @@ window.__ModuleLoader__.load({
|
|
|
8362
9624
|
})]
|
|
8363
9625
|
});
|
|
8364
9626
|
}
|
|
8365
|
-
function useStore$
|
|
9627
|
+
function useStore$2(store) {
|
|
8366
9628
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
8367
9629
|
}
|
|
8368
9630
|
//#endregion
|
|
8369
9631
|
//#region src/client/kimi-code/styles.ts
|
|
8370
|
-
const STYLE_ID$
|
|
9632
|
+
const STYLE_ID$2 = "dsh-kimi-code-settings-style";
|
|
8371
9633
|
/**
|
|
8372
9634
|
* Node the base control styles come from.
|
|
8373
9635
|
*
|
|
@@ -8459,11 +9721,118 @@ window.__ModuleLoader__.load({
|
|
|
8459
9721
|
function installKimiCodeStyles() {
|
|
8460
9722
|
if (typeof document === "undefined" || document.getElementById("dsh-kimi-code-settings-style")) return;
|
|
8461
9723
|
const style = document.createElement("style");
|
|
8462
|
-
style.id = STYLE_ID$
|
|
9724
|
+
style.id = STYLE_ID$2;
|
|
8463
9725
|
style.textContent = BASE;
|
|
8464
9726
|
document.head.appendChild(style);
|
|
8465
9727
|
}
|
|
8466
9728
|
//#endregion
|
|
9729
|
+
//#region src/client/minimax-code/MinimaxCodeComposerQuota.tsx
|
|
9730
|
+
/**
|
|
9731
|
+
* Pick the badge facts for one status answer, or nothing at all.
|
|
9732
|
+
*
|
|
9733
|
+
* Quota is optional in the contract, and the usage read is allowed to fail (the
|
|
9734
|
+
* endpoint is undocumented and which host serves this subscription is
|
|
9735
|
+
* unmeasured), so a status without quota means the badge has nothing to say: it
|
|
9736
|
+
* is not rendered, rather than showing a placeholder that would read as a broken
|
|
9737
|
+
* meter. Callers must treat null as "hide the badge".
|
|
9738
|
+
*/
|
|
9739
|
+
function selectBadgeFacts$1(status) {
|
|
9740
|
+
const quota = status?.quota;
|
|
9741
|
+
if (quota === void 0) return null;
|
|
9742
|
+
if (quota.usedPercent !== void 0 && Number.isFinite(quota.usedPercent)) {
|
|
9743
|
+
const remaining = Math.max(0, Math.round(100 - quota.usedPercent));
|
|
9744
|
+
return {
|
|
9745
|
+
text: `${remaining}%`,
|
|
9746
|
+
tooltip: `[MiniMax Code] ${quota.label}: ${remaining}% left`,
|
|
9747
|
+
level: remaining <= 5 ? "danger" : remaining <= 20 ? "warning" : "normal"
|
|
9748
|
+
};
|
|
9749
|
+
}
|
|
9750
|
+
return {
|
|
9751
|
+
text: quota.label,
|
|
9752
|
+
tooltip: `[MiniMax Code] ${quota.label}`,
|
|
9753
|
+
level: "normal"
|
|
9754
|
+
};
|
|
9755
|
+
}
|
|
9756
|
+
function MinimaxCodeComposerQuota({ t, directory, loadModelDirectory }) {
|
|
9757
|
+
const modelState = useStore$1(directory);
|
|
9758
|
+
const [status, setStatus] = (0, react.useState)(null);
|
|
9759
|
+
const [loading, setLoading] = (0, react.useState)(false);
|
|
9760
|
+
const mountedRef = (0, react.useRef)(false);
|
|
9761
|
+
const isMinimaxCode = modelState.current?.provider === MINIMAX_CODE_PROVIDER_ID;
|
|
9762
|
+
(0, react.useEffect)(() => {
|
|
9763
|
+
loadModelDirectory();
|
|
9764
|
+
}, [loadModelDirectory]);
|
|
9765
|
+
(0, react.useEffect)(() => {
|
|
9766
|
+
mountedRef.current = true;
|
|
9767
|
+
return () => {
|
|
9768
|
+
mountedRef.current = false;
|
|
9769
|
+
};
|
|
9770
|
+
}, []);
|
|
9771
|
+
const fetchStatus = (0, react.useCallback)(async () => {
|
|
9772
|
+
if (!mountedRef.current) return;
|
|
9773
|
+
setLoading(true);
|
|
9774
|
+
try {
|
|
9775
|
+
const data = await get("/quota");
|
|
9776
|
+
if (mountedRef.current) setStatus(data);
|
|
9777
|
+
} catch {} finally {
|
|
9778
|
+
if (mountedRef.current) setLoading(false);
|
|
9779
|
+
}
|
|
9780
|
+
}, []);
|
|
9781
|
+
(0, react.useEffect)(() => {
|
|
9782
|
+
if (!isMinimaxCode) return;
|
|
9783
|
+
fetchStatus();
|
|
9784
|
+
const timer = window.setInterval(() => {
|
|
9785
|
+
if (document.visibilityState === "visible") fetchStatus();
|
|
9786
|
+
}, 6e4);
|
|
9787
|
+
return () => {
|
|
9788
|
+
window.clearInterval(timer);
|
|
9789
|
+
};
|
|
9790
|
+
}, [fetchStatus, isMinimaxCode]);
|
|
9791
|
+
const facts = (0, react.useMemo)(() => selectBadgeFacts$1(status), [status]);
|
|
9792
|
+
if (!isMinimaxCode || !status?.authenticated || facts === null) return null;
|
|
9793
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9794
|
+
className: "dsha-composer-quota",
|
|
9795
|
+
"data-level": facts.level,
|
|
9796
|
+
title: facts.tooltip,
|
|
9797
|
+
"aria-label": facts.tooltip,
|
|
9798
|
+
onClick: () => void fetchStatus(),
|
|
9799
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9800
|
+
className: "dsha-composer-quota-label",
|
|
9801
|
+
children: t("composerLabel")
|
|
9802
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
9803
|
+
className: "dsha-composer-quota-val",
|
|
9804
|
+
children: loading ? "…" : facts.text
|
|
9805
|
+
})]
|
|
9806
|
+
});
|
|
9807
|
+
}
|
|
9808
|
+
function useStore$1(store) {
|
|
9809
|
+
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
9810
|
+
}
|
|
9811
|
+
//#endregion
|
|
9812
|
+
//#region src/client/minimax-code/styles.ts
|
|
9813
|
+
const STYLE_ID$1 = "dsh-minimax-code-settings-style";
|
|
9814
|
+
/**
|
|
9815
|
+
* MiniMax Code-only additions to the shared settings design system.
|
|
9816
|
+
*
|
|
9817
|
+
* The base control styles (.dsha-page, .dsha-group, .dsha-row, .dsha-models,
|
|
9818
|
+
* the device-code box, the meter, the composer badge, ...) come from the
|
|
9819
|
+
* stylesheet the sibling routes install, in the same order the client installs
|
|
9820
|
+
* them, so this file declares only what stays unique to this card: the mono
|
|
9821
|
+
* credential path and the model-name list.
|
|
9822
|
+
*/
|
|
9823
|
+
function installMinimaxCodeStyles() {
|
|
9824
|
+
if (typeof document === "undefined" || document.getElementById("dsh-minimax-code-settings-style")) return;
|
|
9825
|
+
const style = document.createElement("style");
|
|
9826
|
+
style.id = STYLE_ID$1;
|
|
9827
|
+
style.textContent = `
|
|
9828
|
+
.dshm-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px}
|
|
9829
|
+
.dshm-model-list{display:flex;flex-wrap:wrap;gap:7px;padding-top:8px}
|
|
9830
|
+
.dshm-model-list code{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-secondary);font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;padding:5px 8px;white-space:nowrap}
|
|
9831
|
+
.dshm-quota-note{margin-top:12px}
|
|
9832
|
+
`;
|
|
9833
|
+
document.head.append(style);
|
|
9834
|
+
}
|
|
9835
|
+
//#endregion
|
|
8467
9836
|
//#region src/client/workbuddy/WorkBuddyComposerQuota.tsx
|
|
8468
9837
|
const API = "/workbuddy/api";
|
|
8469
9838
|
async function fetchApi(path, options) {
|
|
@@ -8938,22 +10307,27 @@ window.__ModuleLoader__.load({
|
|
|
8938
10307
|
function apply(ctx) {
|
|
8939
10308
|
ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-chatgpt-subscription: dictionaries");
|
|
8940
10309
|
ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
|
|
8941
|
-
ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$
|
|
10310
|
+
ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$6), "dsh-antigravity: dictionaries");
|
|
8942
10311
|
ctx.effect(() => {
|
|
8943
10312
|
installAntigravityStyles();
|
|
8944
10313
|
return () => {};
|
|
8945
10314
|
}, "dsh-antigravity: styles");
|
|
8946
|
-
ctx.effect(() => ctx.locale.register(NS_CLAUDE, dictionaries$
|
|
10315
|
+
ctx.effect(() => ctx.locale.register(NS_CLAUDE, dictionaries$4), "dsh-claude: dictionaries");
|
|
8947
10316
|
ctx.effect(() => {
|
|
8948
10317
|
installClaudeStyles();
|
|
8949
10318
|
return () => {};
|
|
8950
10319
|
}, "dsh-claude: styles");
|
|
8951
|
-
ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$
|
|
8952
|
-
ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$
|
|
10320
|
+
ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$5), "dsh-command-code: dictionaries");
|
|
10321
|
+
ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$3), "dsh-kimi-code: dictionaries");
|
|
8953
10322
|
ctx.effect(() => {
|
|
8954
10323
|
installKimiCodeStyles();
|
|
8955
10324
|
return () => {};
|
|
8956
10325
|
}, "dsh-kimi-code: styles");
|
|
10326
|
+
ctx.effect(() => ctx.locale.register(NS_MINIMAX_CODE, dictionaries$2), "dsh-minimax-code: dictionaries");
|
|
10327
|
+
ctx.effect(() => {
|
|
10328
|
+
installMinimaxCodeStyles();
|
|
10329
|
+
return () => {};
|
|
10330
|
+
}, "dsh-minimax-code: styles");
|
|
8957
10331
|
ctx.effect(() => ctx.locale.register(NS_WORKBUDDY, dictionaries$1), "dsh-workbuddy: dictionaries");
|
|
8958
10332
|
ctx.effect(() => {
|
|
8959
10333
|
installWorkBuddyStyles();
|
|
@@ -9061,6 +10435,21 @@ window.__ModuleLoader__.load({
|
|
|
9061
10435
|
};
|
|
9062
10436
|
}
|
|
9063
10437
|
}, WorkBuddyComposerQuota));
|
|
10438
|
+
ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
|
|
10439
|
+
name: "conversation.input.right",
|
|
10440
|
+
id: "minimax-code-quota",
|
|
10441
|
+
order: 40,
|
|
10442
|
+
locale: NS_MINIMAX_CODE,
|
|
10443
|
+
inject: (sessionId) => {
|
|
10444
|
+
const directory = ctx.modelDirectories.directoryFor(sessionId);
|
|
10445
|
+
return {
|
|
10446
|
+
directory: directory.store,
|
|
10447
|
+
loadModelDirectory: () => {
|
|
10448
|
+
directory.load().catch(() => void 0);
|
|
10449
|
+
}
|
|
10450
|
+
};
|
|
10451
|
+
}
|
|
10452
|
+
}, MinimaxCodeComposerQuota));
|
|
9064
10453
|
ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
|
|
9065
10454
|
name: "conversation.input.right",
|
|
9066
10455
|
id: "claude-quota",
|