@eddyskywalker/dsh-chatgpt-subscription 0.10.0 → 0.10.5

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +39 -1
  3. package/lib/client.js +1675 -208
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +5891 -1342
  6. package/lib/types/client/ProviderHubSection.d.ts.map +1 -1
  7. package/lib/types/client/index.d.ts +2 -0
  8. package/lib/types/client/index.d.ts.map +1 -1
  9. package/lib/types/client/minimax-code/MinimaxCodeComposerQuota.d.ts +27 -0
  10. package/lib/types/client/minimax-code/MinimaxCodeComposerQuota.d.ts.map +1 -0
  11. package/lib/types/client/minimax-code/MinimaxCodeSection.d.ts +49 -0
  12. package/lib/types/client/minimax-code/MinimaxCodeSection.d.ts.map +1 -0
  13. package/lib/types/client/minimax-code/api.d.ts +5 -0
  14. package/lib/types/client/minimax-code/api.d.ts.map +1 -0
  15. package/lib/types/client/minimax-code/locales.d.ts +377 -0
  16. package/lib/types/client/minimax-code/locales.d.ts.map +1 -0
  17. package/lib/types/client/minimax-code/styles.d.ts +12 -0
  18. package/lib/types/client/minimax-code/styles.d.ts.map +1 -0
  19. package/lib/types/client/styles.d.ts.map +1 -1
  20. package/lib/types/compat.d.ts +1 -0
  21. package/lib/types/compat.d.ts.map +1 -1
  22. package/lib/types/host/minimax-code/account-pool.d.ts +219 -0
  23. package/lib/types/host/minimax-code/account-pool.d.ts.map +1 -0
  24. package/lib/types/host/minimax-code/adapter.d.ts +168 -0
  25. package/lib/types/host/minimax-code/adapter.d.ts.map +1 -0
  26. package/lib/types/host/minimax-code/checkin-gateway.d.ts +109 -0
  27. package/lib/types/host/minimax-code/checkin-gateway.d.ts.map +1 -0
  28. package/lib/types/host/minimax-code/checkin.d.ts +150 -0
  29. package/lib/types/host/minimax-code/checkin.d.ts.map +1 -0
  30. package/lib/types/host/minimax-code/client.d.ts +184 -0
  31. package/lib/types/host/minimax-code/client.d.ts.map +1 -0
  32. package/lib/types/host/minimax-code/mapper.d.ts +172 -0
  33. package/lib/types/host/minimax-code/mapper.d.ts.map +1 -0
  34. package/lib/types/host/minimax-code/model-catalog.d.ts +146 -0
  35. package/lib/types/host/minimax-code/model-catalog.d.ts.map +1 -0
  36. package/lib/types/host/minimax-code/oauth.d.ts +204 -0
  37. package/lib/types/host/minimax-code/oauth.d.ts.map +1 -0
  38. package/lib/types/host/minimax-code/routes.d.ts +82 -0
  39. package/lib/types/host/minimax-code/routes.d.ts.map +1 -0
  40. package/lib/types/host/minimax-code/token-store.d.ts +253 -0
  41. package/lib/types/host/minimax-code/token-store.d.ts.map +1 -0
  42. package/lib/types/host/minimax-code/types.d.ts +222 -0
  43. package/lib/types/host/minimax-code/types.d.ts.map +1 -0
  44. package/lib/types/index.d.ts +11 -0
  45. package/lib/types/index.d.ts.map +1 -1
  46. package/lib/types/shared/minimax-code-contracts.d.ts +202 -0
  47. package/lib/types/shared/minimax-code-contracts.d.ts.map +1 -0
  48. package/package.json +31 -31
  49. package/lib/types/host/claude/__probe-assert.d.ts +0 -2
  50. package/lib/types/host/claude/__probe-assert.d.ts.map +0 -1
  51. package/lib/types/shared/__probe-claude-import.d.ts +0 -2
  52. package/lib/types/shared/__probe-claude-import.d.ts.map +0 -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$5(directory);
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$5(store) {
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$5(resolveCodexCatalogEntry(model).contextWindow)
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$4(connection.checkedAt)}`
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$5(fallback),
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$4(quota.fetchedAt)
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$5(value) {
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$5(value);
1715
+ const parsed = parsePositiveCapacity$6(value);
1688
1716
  return parsed !== null && parsed <= maxContextWindow ? parsed : null;
1689
1717
  }
1690
- function formatCapacity$5(value) {
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$4(seconds) {
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$4(seconds);
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$5 = {
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$5 = {
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$5 = {
1883
- zh: zh$5,
1884
- "zh-CN": zh$5,
1885
- en: en$5,
1886
- "en-US": en$5
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$4(value) {
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$4(value) {
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$4(status) {
1948
+ function contextDraftsFor$5(status) {
1921
1949
  const drafts = {};
1922
- for (const model of status.models) drafts[model.id] = formatCapacity$4(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
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$3(ms) {
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$5;
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$4(data));
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$4(updated));
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$4(updated));
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$4(raw);
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$4(parsed)
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$4(model.defaultContextWindow)
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$4(updated));
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$3(account.expiresAt)
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$3(account.lastUsedAt)
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$4 = {
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$4 = {
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$4 = {
2720
- zh: zh$4,
2721
- "zh-CN": zh$4,
2722
- en: en$4,
2723
- "en-US": en$4
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$3(value) {
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$3(value) {
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$3(status) {
2798
+ function contextDraftsFor$4(status) {
2771
2799
  const drafts = {};
2772
- for (const model of status.models) drafts[model.id] = formatCapacity$3(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
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$4;
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$3(data));
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$3(updated));
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$3(updated));
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$3(raw);
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$3(parsed)
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$3(model.defaultContextWindow)
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$3(updated));
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$3 = {
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$3 = {
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$3 = {
3754
- zh: zh$3,
3755
- "zh-CN": zh$3,
3756
- en: en$3,
3757
- "en-US": en$3
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$2(value) {
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$2(value) {
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$2(status) {
3830
+ function contextDraftsFor$3(status) {
3803
3831
  const drafts = {};
3804
- for (const model of status.models) drafts[model.id] = formatCapacity$2(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
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$2(ms) {
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$3.effortLow,
3848
- medium: zh$3.effortMedium,
3849
- high: zh$3.effortHigh,
3850
- xhigh: zh$3.effortXHigh,
3851
- max: zh$3.effortMax
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$3;
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$2(data));
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$2(updated));
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$2(updated));
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$2(updated));
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$2(updated));
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$2(raw);
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$2(parsed)
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$2(model.defaultContextWindow)
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$2(updated));
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$2(model.contextWindow)
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$2(quota.observedAt)) : t.updatedAt.replace("{time}", formatDate$2(quota.fetchedAt))
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$2 = {
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$2 = {
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$2 = {
5097
- zh: zh$2,
5098
- "zh-CN": zh$2,
5099
- en: en$2,
5100
- "en-US": en$2
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$2;
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$1(value) {
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$1(value) {
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$1(status) {
5216
+ function contextDraftsFor$2(status) {
5189
5217
  const drafts = {};
5190
- for (const model of status.models) drafts[model.id] = formatCapacity$1(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
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$1(ms) {
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$2.effortLow,
5230
- high: zh$2.effortHigh,
5231
- max: zh$2.effortMax,
5232
- none: zh$2.effortNone
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$2;
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$1(data));
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$1(updated));
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$1(updated));
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$1(raw);
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$1(parsed)
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$1(model.defaultContextWindow)
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$1(updated));
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$1(flow?.expiresAt)
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$1(model.contextWindow)
5962
+ children: formatCapacity$2(model.contextWindow)
5935
5963
  })]
5936
5964
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5937
5965
  className: "dsha-capacity-control",
@@ -6073,69 +6101,1328 @@ window.__ModuleLoader__.load({
6073
6101
  });
6074
6102
  }
6075
6103
  //#endregion
6076
- //#region src/shared/workbuddy-contracts.ts
6077
- /** Every level this route can name, in escalating order (the card's sort key). */
6078
- const WORKBUDDY_REASONING_EFFORTS = [
6079
- "minimal",
6080
- "low",
6081
- "medium",
6082
- "high",
6083
- "xhigh",
6084
- "max"
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/workbuddy/locales.ts
6088
- const NS_WORKBUDDY = "dsh-workbuddy";
6089
- const zh$1 = {
6090
- title: "WorkBuddy",
6091
- pageDesc: "复用本机 CodeBuddy 桌面端登录态,管理 WorkBuddy(CodeBuddy 订阅)模型、上下文窗口与额度。",
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
- noAccounts: "暂无账号。点击右上角「添加账号」完成浏览器授权,或登录 CodeBuddy 桌面端后重新扫描;桌面账号只能从本插件隐藏,绝不删除 CodeBuddy 的原凭据。",
6094
- signedOut: "未找到凭据",
6095
- nickname: "昵称",
6096
- uin: "UIN",
6166
+ signedIn: "已登录",
6167
+ signedOut: "未登录",
6168
+ accountLabel: "账号标签",
6169
+ accountId: "账号 ID",
6170
+ email: "邮箱",
6097
6171
  region: "区域",
6098
- regionCn: "国区",
6099
- regionIntl: "国际区",
6100
- accountType: "账号类型",
6101
- sourceFile: "凭据文件",
6102
- authDirectory: "凭据目录",
6172
+ regionCn: "中国大陆 (minimax.cn)",
6173
+ regionGlobal: "国际 (minimax.io)",
6103
6174
  storage: "凭据存储",
6104
- storageNotice: "桌面端账号仍读取 CodeBuddy 自己的凭据文件,插件不会删除这些文件;通过这里添加的账号保存在系统加密存储中(Windows DPAPI / macOS Keychain / Linux Secret Service),token 不进入浏览器。",
6105
- routeUnreachable: "无法读取 WorkBuddy 设置路由",
6106
- routeUnreachableHint: "浏览器里加载的插件版本可能比 Host 进程里运行的新(客户端资源是现读磁盘的,Host 只在启动时加载)。请重启 DSH,让两端来自同一份构建。",
6107
- rescan: "重新扫描",
6108
- rescanning: "扫描中...",
6109
- accounts: "账号管理",
6110
- addCnAccount: "添加国区账号",
6111
- addIntlAccount: "添加国际区账号",
6112
- authorizing: "授权中…",
6113
- loginWaiting: "请在新打开的浏览器页面完成登录与授权。",
6114
- loginFailed: "账号授权失败",
6115
- encryptedStorage: "系统加密存储",
6116
- hiddenAccount: "已隐藏",
6117
- hideAccount: "从插件隐藏",
6118
- restoreAccount: "恢复显示",
6119
- deleteAccount: "删除账号",
6120
- deleteConfirm: "确定删除这个插件托管的账号吗?加密存储中的登录凭据会被移除。",
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
- latency: "延迟",
6130
- routeOwned: "模型路由由本插件提供",
6131
- routeConflict: "模型路由已被其他 Provider 占用:{detail}。请在 DSH 设置中移除重复的 Provider 配置后重试。",
6209
+ testSuccess: "连接正常",
6210
+ testSuccessModel: "连接正常({model})",
6211
+ testFailed: "连接失败",
6132
6212
  modelsSection: "模型",
6133
- enableProvider: "启用此供应商",
6134
- modelsHint: "勾选后模型才会出现在对话页的模型选择列表中;未勾选或关闭上方开关可在列表中隐藏该供应商。目录与上下文窗口来自订阅网关的模型目录,并按账号所在区域过滤——跨区调用会被上游拒绝。",
6135
- refreshCatalog: "刷新模型目录",
6136
- refreshingCatalog: "刷新中...",
6137
- selectAll: "全选",
6138
- unselectAll: "全不选",
6213
+ modelsHint: "模型目录由本线路硬编码(MiniMax Code 未开放 /v1/models 接口),当前共 {count} 个可用模型。勾选后模型才会出现在对话页的模型选择列表中;未勾选或关闭下方「启用此供应商」可在列表中隐藏该线路。",
6214
+ modelsUnavailable: "暂无可显示的模型。",
6215
+ quotaSection: "用量与配额",
6216
+ dailyCheckin: "每日签到",
6217
+ checkinHint: "用本线路自己的登录态签到(与官方 MiniMax Code 客户端同一条接口)。DSH 启动时自动签到一次,运行期间每 10 分钟补检,进程关闭的当天不会签到。",
6218
+ checkinAuto: "自动签到",
6219
+ checkinToday: "今日已签 {done}/{total}",
6220
+ checkinSkipped: "{count} 个暂不可签",
6221
+ checkinFailed: "{count} 个失败",
6222
+ checkinStreak: "连续 {days} 天",
6223
+ checkinClaimed: "本轮 +{points} 积分",
6224
+ checkinLastRun: "上次运行:{time}",
6225
+ checkinNever: "尚未运行",
6226
+ checkinNow: "立即签到",
6227
+ checkinRunning: "签到中…",
6228
+ quotaUnavailable: "暂时没有用量数据。",
6229
+ quotaNeedsApiKey: "上游拒绝了这个登录态读取用量(官方客户端的用量端点要求带官方客户端标识头,本插件默认不伪造)。请在 MiniMax 控制台的用量条里查看 Token Plan 用量;如果你接受该取舍,可设 DSH_MINIMAX_CODE_QUOTA_ATTRIBUTION=1 后重试。",
6230
+ quotaUnreachable: "暂时读不到用量(用量端点未应答),稍后会自动重试。",
6231
+ quotaUsed: "已用 {percent}%",
6232
+ quotaRemaining: "剩余 {percent}%",
6233
+ quotaReset: "重置:{time}",
6234
+ quotaRefresh: "刷新用量",
6235
+ quotaRefreshing: "刷新中...",
6236
+ quotaWindowInterval: "5 小时窗口",
6237
+ quotaWindowWeekly: "每周窗口",
6238
+ quotaUnlimited: "不限量",
6239
+ quotaCounts: "已用 {used} / {total}",
6240
+ composerLabel: "额度",
6241
+ enableProvider: "启用此供应商",
6242
+ selectAll: "全选",
6243
+ unselectAll: "全不选",
6244
+ enhanced: "增强功能",
6245
+ defaultReasoningEffort: "默认思考深度",
6246
+ defaultReasoningEffortHint: "控制支持推理的模型在未单独指定时的思考强度。",
6247
+ defaultEffortAuto: "自动(各模型默认)",
6248
+ contextWindowSection: "模型上下文窗口",
6249
+ contextWindowHint: "默认值来自订阅网关的模型目录(每个模型的真实上下文上限);可覆盖为自定义容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
6250
+ contextWindowNoneEnabled: "尚未勾选任何模型,先在上方「模型」中勾选。",
6251
+ contextWindowReset: "恢复默认",
6252
+ contextWindowResetAll: "全部恢复默认",
6253
+ tokens: "tokens",
6254
+ save: "保存",
6255
+ saving: "保存中...",
6256
+ invalidCapacity: "容量格式无效:{value}",
6257
+ thinkingAlwaysOn: "恒定开启(无档位)",
6258
+ thinkingToggle: "可关闭",
6259
+ thinkingForced: "强制开启(可选档位)",
6260
+ capText: "文本",
6261
+ capImage: "图片",
6262
+ loading: "加载中...",
6263
+ unknown: "—"
6264
+ };
6265
+ const en$2 = {
6266
+ ...accountPoolEn,
6267
+ title: "MiniMax Code",
6268
+ 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.",
6269
+ account: "Account",
6270
+ signedIn: "Signed in",
6271
+ signedOut: "Not signed in",
6272
+ accountLabel: "Account label",
6273
+ accountId: "Account ID",
6274
+ email: "Email",
6275
+ region: "Region",
6276
+ regionCn: "Mainland China (minimax.cn)",
6277
+ regionGlobal: "Global (minimax.io)",
6278
+ storage: "Credential storage",
6279
+ storageNative: "MiniMax Code native credential (~/.minimax/auth)",
6280
+ storageDpapi: "Windows DPAPI (current-user encrypted)",
6281
+ storageFile: "Local credential file",
6282
+ storagePath: "Credential path",
6283
+ expiresAt: "Token expires",
6284
+ expiresRemaining: "{hours} h left",
6285
+ expiresExpired: "Expired",
6286
+ 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.",
6287
+ signIn: "Sign in to MiniMax Code",
6288
+ signingIn: "Requesting a device code...",
6289
+ signOut: "Sign out",
6290
+ cancelSignIn: "Cancel",
6291
+ deviceCodeSection: "Device authorization",
6292
+ 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.",
6293
+ userCode: "User code",
6294
+ copyCode: "Copy user code",
6295
+ copied: "Copied",
6296
+ openSignInPage: "Open the sign-in page",
6297
+ codeExpires: "Device code expires",
6298
+ codeMinutes: "{minutes} min left",
6299
+ waitingAuthorization: "Waiting for browser authorization...",
6300
+ loginFailed: "Sign-in failed",
6301
+ loginExpired: "The device code expired — start the sign-in again.",
6302
+ loginDenied: "Authorization was denied.",
6303
+ 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.",
6304
+ connection: "Connection",
6305
+ provider: "Provider",
6306
+ connectionState: "Connection state",
6307
+ connected: "Connected",
6308
+ untested: "Untested",
6309
+ routeOwned: "This plugin serves the model route.",
6310
+ routeConflict: "Another provider already owns the model route: {detail}. Remove the duplicate provider configuration in DSH settings and reload.",
6311
+ testConnection: "Test connection",
6312
+ testingConnection: "Testing...",
6313
+ testSuccess: "Connection OK",
6314
+ testSuccessModel: "Connection OK ({model})",
6315
+ testFailed: "Connection failed",
6316
+ modelsSection: "Models",
6317
+ 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.",
6318
+ modelsUnavailable: "No model to show yet.",
6319
+ quotaSection: "Usage & quota",
6320
+ dailyCheckin: "Daily check-in",
6321
+ checkinHint: "Signs in with this line’s own credential (the same interface the official MiniMax Code client uses). The host signs in once at startup and re-checks every 10 minutes while running; a day the process never runs is not signed.",
6322
+ checkinAuto: "Auto check-in",
6323
+ checkinToday: "Checked in today {done}/{total}",
6324
+ checkinSkipped: "{count} not claimable yet",
6325
+ checkinFailed: "{count} failed",
6326
+ checkinStreak: "{days}-day streak",
6327
+ checkinClaimed: "+{points} credits this run",
6328
+ checkinLastRun: "Last run: {time}",
6329
+ checkinNever: "Never run",
6330
+ checkinNow: "Check in now",
6331
+ checkinRunning: "Checking in…",
6332
+ quotaUnavailable: "No usage data yet.",
6333
+ 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.",
6334
+ quotaUnreachable: "Usage is temporarily unreadable (the usage endpoint did not answer); this retries on its own.",
6335
+ quotaUsed: "{percent}% used",
6336
+ quotaRemaining: "{percent}% left",
6337
+ quotaReset: "Resets: {time}",
6338
+ quotaRefresh: "Refresh usage",
6339
+ quotaRefreshing: "Refreshing...",
6340
+ quotaWindowInterval: "5-hour window",
6341
+ quotaWindowWeekly: "Weekly window",
6342
+ quotaUnlimited: "Unlimited",
6343
+ quotaCounts: "{used} / {total} used",
6344
+ composerLabel: "Quota",
6345
+ enableProvider: "Enable this provider",
6346
+ selectAll: "Select all",
6347
+ unselectAll: "Unselect all",
6348
+ enhanced: "Enhanced",
6349
+ defaultReasoningEffort: "Default reasoning effort",
6350
+ defaultReasoningEffortHint: "Thinking strength for reasoning models when the conversation does not pick one.",
6351
+ defaultEffortAuto: "Auto (each model default)",
6352
+ contextWindowSection: "Model context windows",
6353
+ 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.",
6354
+ contextWindowNoneEnabled: "No model is checked yet — pick one in \"Models\" above.",
6355
+ contextWindowReset: "Restore default",
6356
+ contextWindowResetAll: "Restore all defaults",
6357
+ tokens: "tokens",
6358
+ save: "Save",
6359
+ saving: "Saving...",
6360
+ invalidCapacity: "Invalid capacity: {value}",
6361
+ thinkingAlwaysOn: "Always on (no level)",
6362
+ thinkingToggle: "Can be disabled",
6363
+ thinkingForced: "Forced on (level selectable)",
6364
+ capText: "Text",
6365
+ capImage: "Image",
6366
+ loading: "Loading...",
6367
+ unknown: "—"
6368
+ };
6369
+ const dictionaries$2 = {
6370
+ zh: zh$2,
6371
+ "zh-CN": zh$2,
6372
+ en: en$2,
6373
+ "en-US": en$2
6374
+ };
6375
+ //#endregion
6376
+ //#region src/client/minimax-code/MinimaxCodeSection.tsx
6377
+ /**
6378
+ * The shared pool card's labels, resolved through this card's dictionary.
6379
+ *
6380
+ * The sibling tabs hand the shared card their raw `zh` object, which works because
6381
+ * they render `zh` directly. This card renders through a translate function
6382
+ * instead, so the same label set is assembled here by looking each key up. It is
6383
+ * derived from the shared ZH label object's own keys, so a label added to the
6384
+ * shared card cannot be silently missed — the `satisfies` below turns that into a
6385
+ * compile error.
6386
+ */
6387
+ function accountPoolLabelsFor(t) {
6388
+ return {
6389
+ accountPool: t("accountPool"),
6390
+ addAccount: t("addAccount"),
6391
+ accountCount: t("accountCount"),
6392
+ primaryAccount: t("primaryAccount"),
6393
+ activeAccount: t("activeAccount"),
6394
+ setPrimary: t("setPrimary"),
6395
+ deleteAccount: t("deleteAccount"),
6396
+ cooling: t("cooling"),
6397
+ cooldownLeft: t("cooldownLeft"),
6398
+ clearCooldown: t("clearCooldown"),
6399
+ needsRelogin: t("needsRelogin"),
6400
+ relogin: t("relogin"),
6401
+ rotationStrategy: t("rotationStrategy"),
6402
+ strategySequential: t("strategySequential"),
6403
+ strategyRoundRobin: t("strategyRoundRobin"),
6404
+ strategySticky: t("strategySticky"),
6405
+ noAccounts: t("noAccounts"),
6406
+ storage: t("storage"),
6407
+ storageNotice: t("storageNotice"),
6408
+ email: t("email"),
6409
+ expires: t("expiresAt"),
6410
+ lastUsed: t("lastUsed"),
6411
+ accountId: t("accountId")
6412
+ };
6413
+ }
6414
+ /** Device-code poll cadence. The host owns the real expiry. */
6415
+ const LOGIN_POLL_INTERVAL_MS = 2e3;
6416
+ /**
6417
+ * Parse "1M", "512K", "200000" into a positive integer token count.
6418
+ *
6419
+ * Every provider card carries its own copy of this pair rather than importing one
6420
+ * from a shared module; the value is user input in a free-text field and a bad
6421
+ * parse silently corrupts the overflow judgement, so it stays next to the only
6422
+ * field that produces it.
6423
+ */
6424
+ function parsePositiveCapacity$1(value) {
6425
+ const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
6426
+ if (matched === null) return null;
6427
+ const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
6428
+ const parsed = Number(matched[1]) * multiplier;
6429
+ return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
6430
+ }
6431
+ /** Render a token capacity the way the capacity field seeds itself. */
6432
+ function formatCapacity$1(value) {
6433
+ if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
6434
+ if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
6435
+ return String(value);
6436
+ }
6437
+ /**
6438
+ * Seed one draft per model from a status payload.
6439
+ *
6440
+ * Run after a model toggle too: a model that was just enabled has no draft yet,
6441
+ * and the context-window section only renders enabled models.
6442
+ */
6443
+ function contextDraftsFor$1(status) {
6444
+ const drafts = {};
6445
+ for (const model of status.models) drafts[model.id] = formatCapacity$1(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
6446
+ return drafts;
6447
+ }
6448
+ /** Human label per thinking mode, so the card states what the model does. */
6449
+ function thinkingLabel(mode, t) {
6450
+ if (mode === "always-on") return t("thinkingAlwaysOn");
6451
+ if (mode === "forced-effort") return t("thinkingForced");
6452
+ return t("thinkingToggle");
6453
+ }
6454
+ /** The card's own dictionary; stable identity keeps effect dependencies intact. */
6455
+ const fallbackTranslate = (key) => zh$2[key];
6456
+ /**
6457
+ * Hours still left on the access token, or null once it has run out.
6458
+ *
6459
+ * MiniMax Code's token lives about 24 hours, so hours are the unit the card
6460
+ * reports; a value worth a fraction of an hour keeps one decimal instead of
6461
+ * rounding down to 0.
6462
+ */
6463
+ function remainingHours(expiresAtMs) {
6464
+ if (expiresAtMs === void 0 || !Number.isFinite(expiresAtMs) || expiresAtMs <= 0) return null;
6465
+ const hours = (expiresAtMs - Date.now()) / 36e5;
6466
+ if (hours <= 0) return null;
6467
+ return hours >= 10 ? hours.toFixed(0) : hours.toFixed(1);
6468
+ }
6469
+ function storageLabel(storage, t) {
6470
+ if (storage === void 0) return t("unknown");
6471
+ switch (storage.kind) {
6472
+ case "minimax-native": return t("storageNative");
6473
+ case "dpapi": return t("storageDpapi");
6474
+ default: return t("storageFile");
6475
+ }
6476
+ }
6477
+ function formatDate$1(ms) {
6478
+ if (ms === void 0 || !Number.isFinite(ms) || ms <= 0) return "—";
6479
+ try {
6480
+ return new Intl.DateTimeFormat(void 0, {
6481
+ dateStyle: "medium",
6482
+ timeStyle: "short"
6483
+ }).format(ms);
6484
+ } catch {
6485
+ return "—";
6486
+ }
6487
+ }
6488
+ function MinimaxCodeSection({ onModelChange }) {
6489
+ const t = fallbackTranslate;
6490
+ const [status, setStatus] = (0, react.useState)(null);
6491
+ const [loading, setLoading] = (0, react.useState)(true);
6492
+ const [busy, setBusy] = (0, react.useState)(null);
6493
+ const [error, setError] = (0, react.useState)(null);
6494
+ const [flow, setFlow] = (0, react.useState)(null);
6495
+ const [copied, setCopied] = (0, react.useState)(false);
6496
+ const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
6497
+ const [contextDrafts, setContextDrafts] = (0, react.useState)({});
6498
+ const [savingModel, setSavingModel] = (0, react.useState)(null);
6499
+ const [pool, setPool] = (0, react.useState)(void 0);
6500
+ const loadStatus = (0, react.useCallback)(async (quiet = false) => {
6501
+ if (!quiet) setError(null);
6502
+ try {
6503
+ const next = await get("/status");
6504
+ setStatus(next);
6505
+ setContextDrafts(contextDraftsFor$1(next));
6506
+ } catch (cause) {
6507
+ if (!quiet) setError(messageOf(cause));
6508
+ } finally {
6509
+ setLoading(false);
6510
+ }
6511
+ }, []);
6512
+ (0, react.useEffect)(() => {
6513
+ loadStatus();
6514
+ loadPool();
6515
+ const refreshWhenVisible = () => {
6516
+ if (document.visibilityState === "visible") {
6517
+ loadStatus(true);
6518
+ loadPool();
6519
+ }
6520
+ };
6521
+ document.addEventListener("visibilitychange", refreshWhenVisible);
6522
+ const timer = window.setInterval(refreshWhenVisible, 6e4);
6523
+ return () => {
6524
+ window.clearInterval(timer);
6525
+ document.removeEventListener("visibilitychange", refreshWhenVisible);
6526
+ };
6527
+ }, [loadStatus]);
6528
+ const loginId = flow?.loginId;
6529
+ (0, react.useEffect)(() => {
6530
+ if (loginId === void 0) return;
6531
+ let stopped = false;
6532
+ const timer = window.setInterval(() => {
6533
+ (async () => {
6534
+ try {
6535
+ const poll = await post("/login/poll", { loginId });
6536
+ if (stopped || poll.status === "pending") return;
6537
+ stopped = true;
6538
+ window.clearInterval(timer);
6539
+ setFlow(null);
6540
+ if (poll.status === "authenticated") {
6541
+ await loadStatus();
6542
+ onModelChange?.();
6543
+ return;
6544
+ }
6545
+ setError(poll.status === "expired" ? t("loginExpired") : t("loginDenied"));
6546
+ } catch {}
6547
+ })();
6548
+ }, LOGIN_POLL_INTERVAL_MS);
6549
+ return () => {
6550
+ stopped = true;
6551
+ window.clearInterval(timer);
6552
+ };
6553
+ }, [
6554
+ loginId,
6555
+ loadStatus,
6556
+ onModelChange,
6557
+ t
6558
+ ]);
6559
+ /**
6560
+ * Fetch the usage snapshot once, the first time the card sees a signed-in
6561
+ * account without one.
6562
+ *
6563
+ * The status route refreshes usage BEHIND its answer, so it never blocks on a
6564
+ * network read; that means the very first paint has no snapshot. Asking here
6565
+ * fills the section immediately instead of leaving it empty for a whole poll
6566
+ * interval. A failure is silent on purpose: the section already explains that no
6567
+ * usage is available, and a usage read must never surface as an error banner.
6568
+ */
6569
+ const authenticated = status?.authenticated === true;
6570
+ const quotaRequested = (0, react.useRef)(false);
6571
+ (0, react.useEffect)(() => {
6572
+ if (quotaRequested.current || !authenticated || status?.quota !== void 0) return;
6573
+ quotaRequested.current = true;
6574
+ (async () => {
6575
+ try {
6576
+ setStatus(await post("/quota"));
6577
+ } catch {}
6578
+ })();
6579
+ }, [authenticated, status?.quota]);
6580
+ const handleLogin = async () => {
6581
+ try {
6582
+ setBusy("login");
6583
+ setError(null);
6584
+ setConnectionNotice(null);
6585
+ setCopied(false);
6586
+ const started = await post("/login/start");
6587
+ const login = started.login ?? (typeof started.loginId === "string" ? started : void 0);
6588
+ if (login === void 0) {
6589
+ setError(t("loginFailed"));
6590
+ return;
6591
+ }
6592
+ setFlow(login);
6593
+ } catch (cause) {
6594
+ setError(messageOf(cause));
6595
+ } finally {
6596
+ setBusy(null);
6597
+ }
6598
+ };
6599
+ const handleCancelLogin = async () => {
6600
+ const pending = flow;
6601
+ setFlow(null);
6602
+ if (pending === null) return;
6603
+ try {
6604
+ await post("/login/cancel", { loginId: pending.loginId });
6605
+ } catch (cause) {
6606
+ setError(messageOf(cause));
6607
+ }
6608
+ };
6609
+ const handleCopyCode = async () => {
6610
+ const code = flow?.userCode;
6611
+ if (code === void 0 || code === "") return;
6612
+ try {
6613
+ await navigator.clipboard.writeText(code);
6614
+ setCopied(true);
6615
+ window.setTimeout(() => setCopied(false), 2e3);
6616
+ } catch {}
6617
+ };
6618
+ const handleLogout = async () => {
6619
+ try {
6620
+ setBusy("logout");
6621
+ setError(null);
6622
+ setConnectionNotice(null);
6623
+ setFlow(null);
6624
+ const result = await post("/logout");
6625
+ if (result.native === true) setConnectionNotice(result.error ?? t("logoutOwnedByApp"));
6626
+ await loadStatus(true);
6627
+ onModelChange?.();
6628
+ } catch (cause) {
6629
+ setError(messageOf(cause));
6630
+ await loadStatus(true);
6631
+ } finally {
6632
+ setBusy(null);
6633
+ }
6634
+ };
6635
+ /**
6636
+ * Apply one model-selection patch through `/models`.
6637
+ *
6638
+ * The host owns the selection and answers with the whole fresh status, so the
6639
+ * card never guesses which ids ended up enabled.
6640
+ */
6641
+ /** Re-read the pool slice, which lives beside the status on its own route. */
6642
+ const loadPool = (0, react.useCallback)(async () => {
6643
+ try {
6644
+ const next = await get("/accounts");
6645
+ setPool(next);
6646
+ } catch {
6647
+ setPool(void 0);
6648
+ }
6649
+ }, []);
6650
+ /** Run one account action, then re-read both the pool and the status. */
6651
+ const poolAction = async (action, accountId) => {
6652
+ try {
6653
+ setBusy(action);
6654
+ setError(null);
6655
+ await post("/accounts", {
6656
+ action,
6657
+ accountId
6658
+ });
6659
+ await loadPool();
6660
+ await loadStatus(true);
6661
+ onModelChange?.();
6662
+ } catch (cause) {
6663
+ setError(messageOf(cause));
6664
+ } finally {
6665
+ setBusy(null);
6666
+ }
6667
+ };
6668
+ const poolSetStrategy = async (strategy) => {
6669
+ try {
6670
+ setBusy("strategy");
6671
+ setError(null);
6672
+ await post("/accounts", {
6673
+ action: "strategy",
6674
+ strategy
6675
+ });
6676
+ await loadPool();
6677
+ } catch (cause) {
6678
+ setError(messageOf(cause));
6679
+ } finally {
6680
+ setBusy(null);
6681
+ }
6682
+ };
6683
+ const applyEnabled = async (enabledModelIds) => {
6684
+ try {
6685
+ setError(null);
6686
+ const updated = await post("/models", { enabledModelIds });
6687
+ setStatus(updated);
6688
+ setContextDrafts(contextDraftsFor$1(updated));
6689
+ onModelChange?.();
6690
+ } catch (cause) {
6691
+ setError(messageOf(cause));
6692
+ }
6693
+ };
6694
+ /**
6695
+ * Flip the line's own switch.
6696
+ *
6697
+ * Optimistic on purpose: the checkbox is the one control whose state the user
6698
+ * is looking straight at, and a failed round trip re-reads the truth below
6699
+ * rather than leaving the box in a state the host never accepted.
6700
+ */
6701
+ const toggleEnabled = async (enabled) => {
6702
+ setStatus((prev) => prev === null ? prev : {
6703
+ ...prev,
6704
+ enabled
6705
+ });
6706
+ try {
6707
+ setError(null);
6708
+ const updated = await post("/settings", { enabled });
6709
+ setStatus(updated);
6710
+ onModelChange?.();
6711
+ } catch (cause) {
6712
+ setError(messageOf(cause));
6713
+ await loadStatus(true);
6714
+ }
6715
+ };
6716
+ /** Flip the check-in scheduler's own switch, through the same settings route. */
6717
+ const handleCheckinToggle = async (enabled) => {
6718
+ try {
6719
+ setBusy("checkin");
6720
+ setError(null);
6721
+ const updated = await post("/settings", { checkin: { enabled } });
6722
+ setStatus(updated);
6723
+ } catch (cause) {
6724
+ setError(messageOf(cause));
6725
+ } finally {
6726
+ setBusy(null);
6727
+ }
6728
+ };
6729
+ /** Run one check-in pass now: the toggle and the retry cap are bypassed. */
6730
+ const handleCheckinNow = async () => {
6731
+ try {
6732
+ setBusy("checkin");
6733
+ setError(null);
6734
+ const updated = await post("/checkin/now");
6735
+ setStatus(updated);
6736
+ } catch (cause) {
6737
+ setError(messageOf(cause));
6738
+ } finally {
6739
+ setBusy(null);
6740
+ }
6741
+ };
6742
+ const toggleModel = (modelId, checked) => {
6743
+ if (status === null) return;
6744
+ const current = status.models.filter((model) => model.enabled).map((model) => model.id);
6745
+ const next = checked ? [.../* @__PURE__ */ new Set([...current, modelId])] : current.filter((id) => id !== modelId);
6746
+ applyEnabled(next);
6747
+ };
6748
+ const setAllModels = (selectAll) => {
6749
+ if (status === null || status.models.length === 0) return;
6750
+ applyEnabled(selectAll ? status.models.map((model) => model.id) : []);
6751
+ };
6752
+ const handleUpdateEffort = async (effort) => {
6753
+ try {
6754
+ setError(null);
6755
+ const updated = await post("/settings", { defaultReasoningEffort: effort });
6756
+ setStatus(updated);
6757
+ onModelChange?.();
6758
+ } catch (cause) {
6759
+ setError(messageOf(cause));
6760
+ }
6761
+ };
6762
+ const handleSaveContextWindow = async (modelId) => {
6763
+ const raw = contextDrafts[modelId] ?? "";
6764
+ const parsed = parsePositiveCapacity$1(raw);
6765
+ if (parsed === null) {
6766
+ setError(t("invalidCapacity").replace("{value}", raw));
6767
+ return;
6768
+ }
6769
+ try {
6770
+ setSavingModel(modelId);
6771
+ setError(null);
6772
+ const updated = await post("/settings", { contextWindowOverrides: { [modelId]: parsed } });
6773
+ setStatus(updated);
6774
+ setContextDrafts((prev) => ({
6775
+ ...prev,
6776
+ [modelId]: formatCapacity$1(parsed)
6777
+ }));
6778
+ onModelChange?.();
6779
+ } catch (cause) {
6780
+ setError(messageOf(cause));
6781
+ } finally {
6782
+ setSavingModel(null);
6783
+ }
6784
+ };
6785
+ const handleResetContextWindow = async (modelId) => {
6786
+ try {
6787
+ setSavingModel(modelId);
6788
+ setError(null);
6789
+ const updated = await post("/settings", { contextWindowOverrides: { [modelId]: null } });
6790
+ setStatus(updated);
6791
+ const model = updated.models.find((entry) => entry.id === modelId);
6792
+ if (model !== void 0) setContextDrafts((prev) => ({
6793
+ ...prev,
6794
+ [modelId]: formatCapacity$1(model.defaultContextWindow)
6795
+ }));
6796
+ onModelChange?.();
6797
+ } catch (cause) {
6798
+ setError(messageOf(cause));
6799
+ } finally {
6800
+ setSavingModel(null);
6801
+ }
6802
+ };
6803
+ const handleResetAllContextWindows = async () => {
6804
+ const ids = Object.keys(status?.contextWindowOverrides ?? {});
6805
+ if (ids.length === 0) return;
6806
+ try {
6807
+ setError(null);
6808
+ const updated = await post("/settings", { contextWindowOverrides: Object.fromEntries(ids.map((id) => [id, null])) });
6809
+ setStatus(updated);
6810
+ setContextDrafts(contextDraftsFor$1(updated));
6811
+ onModelChange?.();
6812
+ } catch (cause) {
6813
+ setError(messageOf(cause));
6814
+ }
6815
+ };
6816
+ /** Force one usage read through `/quota` and render the fresh status. */
6817
+ const handleRefreshQuota = async () => {
6818
+ try {
6819
+ setBusy("quota");
6820
+ setError(null);
6821
+ setStatus(await post("/quota"));
6822
+ } catch (cause) {
6823
+ setError(messageOf(cause));
6824
+ } finally {
6825
+ setBusy(null);
6826
+ }
6827
+ };
6828
+ const handleTestConnection = async () => {
6829
+ try {
6830
+ setBusy("test");
6831
+ setError(null);
6832
+ setConnectionNotice(null);
6833
+ const result = await post("/test");
6834
+ if (result.ok === true) {
6835
+ setConnectionNotice(result.model === void 0 || result.model === "" ? t("testSuccess") : t("testSuccessModel").replace("{model}", result.model));
6836
+ return;
6837
+ }
6838
+ setConnectionNotice(result.error === void 0 || result.error === "" ? t("testFailed") : `${t("testFailed")}:${result.error}`);
6839
+ } catch (cause) {
6840
+ setConnectionNotice(`${t("testFailed")}:${messageOf(cause)}`);
6841
+ } finally {
6842
+ setBusy(null);
6843
+ }
6844
+ };
6845
+ if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6846
+ className: "dsha-page",
6847
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6848
+ className: "dsha-empty",
6849
+ children: t("loading")
6850
+ })
6851
+ });
6852
+ const account = status?.account;
6853
+ const quota = status?.quota;
6854
+ const models = status?.models ?? [];
6855
+ const hours = remainingHours(account?.expiresAtMs);
6856
+ const storage = status?.storage;
6857
+ const contextModels = status?.models.filter((model) => model.enabled) ?? [];
6858
+ const overrideCount = Object.keys(status?.contextWindowOverrides ?? {}).length;
6859
+ const quotaWindows = quota?.windows ?? (quota === void 0 || quota.usedPercent === void 0 ? [] : [{
6860
+ key: "interval",
6861
+ remainingPercent: Math.max(0, 100 - quota.usedPercent),
6862
+ usedPercent: quota.usedPercent,
6863
+ ...quota.resetsAtMs === void 0 ? {} : { resetsAtMs: quota.resetsAtMs }
6864
+ }]);
6865
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6866
+ className: "dsha-page",
6867
+ children: [
6868
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6869
+ className: "dsha-muted",
6870
+ children: t("pageDesc")
6871
+ }),
6872
+ pool !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
6873
+ labels: accountPoolLabelsFor(t),
6874
+ accounts: pool.accounts,
6875
+ rotationStrategy: pool.rotationStrategy,
6876
+ ...pool.activeAccountId === void 0 ? {} : { activeAccountId: pool.activeAccountId },
6877
+ busy,
6878
+ storageValue: storageLabel(status?.storage, t),
6879
+ onLogin: () => void handleLogin(),
6880
+ onSetPrimary: (accountId) => void poolAction("set-primary", accountId),
6881
+ onDelete: (accountId) => void poolAction("delete", accountId),
6882
+ onClearCooldown: (accountId) => void poolAction("clear-cooldown", accountId),
6883
+ onSetStrategy: (strategy) => void poolSetStrategy(strategy)
6884
+ }),
6885
+ status?.checkin != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6886
+ className: "dsha-group",
6887
+ children: [
6888
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6889
+ className: "dsha-grouphead",
6890
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("dailyCheckin") })
6891
+ }),
6892
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6893
+ className: "dsha-muted",
6894
+ children: t("checkinHint")
6895
+ }),
6896
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6897
+ className: "dsha-row",
6898
+ style: { marginBottom: 8 },
6899
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6900
+ className: "dsha-label",
6901
+ style: { fontWeight: 600 },
6902
+ children: t("checkinAuto")
6903
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6904
+ type: "checkbox",
6905
+ checked: status.checkin.enabled,
6906
+ disabled: busy !== null,
6907
+ onChange: (event) => void handleCheckinToggle(event.currentTarget.checked)
6908
+ })]
6909
+ }),
6910
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6911
+ className: "dsha-row",
6912
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6913
+ className: "dsha-label",
6914
+ children: t("dailyCheckin")
6915
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6916
+ className: "dsha-value",
6917
+ children: [
6918
+ t("checkinToday").replace("{done}", String(status.checkin.doneToday)).replace("{total}", String(status.checkin.totalAccounts)),
6919
+ status.checkin.skippedToday > 0 ? ` · ${t("checkinSkipped").replace("{count}", String(status.checkin.skippedToday))}` : "",
6920
+ status.checkin.failedToday > 0 ? ` · ${t("checkinFailed").replace("{count}", String(status.checkin.failedToday))}` : "",
6921
+ status.checkin.streakDays !== void 0 ? ` · ${t("checkinStreak").replace("{days}", String(status.checkin.streakDays))}` : "",
6922
+ status.checkin.claimedPoints !== void 0 ? ` · ${t("checkinClaimed").replace("{points}", String(status.checkin.claimedPoints))}` : "",
6923
+ ` · ${status.checkin.lastRunAt === null ? t("checkinNever") : t("checkinLastRun").replace("{time}", formatDate$1(status.checkin.lastRunAt))}`
6924
+ ]
6925
+ })]
6926
+ }),
6927
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6928
+ className: "dsha-actions",
6929
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6930
+ className: "dsha-btn",
6931
+ disabled: busy !== null,
6932
+ onClick: () => void handleCheckinNow(),
6933
+ children: busy === "checkin" ? t("checkinRunning") : t("checkinNow")
6934
+ })
6935
+ })
6936
+ ]
6937
+ }) : null,
6938
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6939
+ className: "dsha-group",
6940
+ children: [
6941
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6942
+ className: "dsha-grouphead",
6943
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("account") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6944
+ className: "dsha-value",
6945
+ children: authenticated ? t("signedIn") : t("signedOut")
6946
+ })]
6947
+ }),
6948
+ authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
6949
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6950
+ className: "dsha-row",
6951
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6952
+ className: "dsha-label",
6953
+ children: t("accountLabel")
6954
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6955
+ className: "dsha-value",
6956
+ children: account?.label !== void 0 && account.label !== "" ? account.label : t("unknown")
6957
+ })]
6958
+ }),
6959
+ account?.id !== void 0 && account.id !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6960
+ className: "dsha-row",
6961
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6962
+ className: "dsha-label",
6963
+ children: t("accountId")
6964
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6965
+ className: "dsha-value dshm-mono",
6966
+ children: account.id
6967
+ })]
6968
+ }),
6969
+ account?.email !== void 0 && account.email !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6970
+ className: "dsha-row",
6971
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6972
+ className: "dsha-label",
6973
+ children: t("email")
6974
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6975
+ className: "dsha-value",
6976
+ children: account.email
6977
+ })]
6978
+ }),
6979
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6980
+ className: "dsha-row",
6981
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6982
+ className: "dsha-label",
6983
+ children: t("expiresAt")
6984
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6985
+ className: "dsha-value",
6986
+ children: [formatDate$1(account?.expiresAtMs), hours === null ? ` · ${t("expiresExpired")}` : ` · ${t("expiresRemaining").replace("{hours}", hours)}`]
6987
+ })]
6988
+ })
6989
+ ] }),
6990
+ status !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
6991
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6992
+ className: "dsha-row",
6993
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6994
+ className: "dsha-label",
6995
+ children: t("region")
6996
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6997
+ className: "dsha-value",
6998
+ children: status.region === "global" ? t("regionGlobal") : t("regionCn")
6999
+ })]
7000
+ }),
7001
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7002
+ className: "dsha-row",
7003
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7004
+ className: "dsha-label",
7005
+ children: t("storage")
7006
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7007
+ className: "dsha-value",
7008
+ children: storageLabel(storage, t)
7009
+ })]
7010
+ }),
7011
+ storage?.path !== void 0 && storage.path !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7012
+ className: "dsha-row",
7013
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7014
+ className: "dsha-label",
7015
+ children: t("storagePath")
7016
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7017
+ className: "dsha-value dshm-mono",
7018
+ children: storage.path
7019
+ })]
7020
+ }),
7021
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7022
+ className: "dsha-notice",
7023
+ children: t("expiresHint")
7024
+ })
7025
+ ] }),
7026
+ flow !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7027
+ className: "dsha-device-box",
7028
+ children: [
7029
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("deviceCodeSection") }),
7030
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7031
+ className: "dsha-muted",
7032
+ children: t("deviceCodeHint")
7033
+ }),
7034
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7035
+ className: "dsha-code-row",
7036
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7037
+ className: "dsha-code",
7038
+ "aria-label": t("userCode"),
7039
+ children: flow.userCode
7040
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7041
+ className: "dsha-btn",
7042
+ onClick: () => void handleCopyCode(),
7043
+ children: copied ? t("copied") : t("copyCode")
7044
+ })]
7045
+ }),
7046
+ flow.verificationUri !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
7047
+ className: "dsha-link",
7048
+ href: flow.verificationUri,
7049
+ target: "_blank",
7050
+ rel: "noreferrer noopener",
7051
+ children: flow.verificationUri
7052
+ }),
7053
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7054
+ className: "dsha-row",
7055
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7056
+ className: "dsha-label",
7057
+ children: t("codeExpires")
7058
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7059
+ className: "dsha-value",
7060
+ children: t("codeMinutes").replace("{minutes}", String(Math.max(1, Math.round(flow.expiresInSec / 60))))
7061
+ })]
7062
+ }),
7063
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7064
+ className: "dsha-muted",
7065
+ children: t("waitingAuthorization")
7066
+ }),
7067
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7068
+ className: "dsha-actions",
7069
+ children: [flow.verificationUri !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
7070
+ className: "dsha-btn",
7071
+ href: flow.verificationUri,
7072
+ target: "_blank",
7073
+ rel: "noreferrer noopener",
7074
+ children: t("openSignInPage")
7075
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7076
+ className: "dsha-btn",
7077
+ onClick: () => void handleCancelLogin(),
7078
+ children: t("cancelSignIn")
7079
+ })]
7080
+ })
7081
+ ]
7082
+ }),
7083
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7084
+ className: "dsha-actions",
7085
+ children: [flow === null && !authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7086
+ className: "dsha-btn dsha-btn-primary",
7087
+ disabled: busy !== null,
7088
+ onClick: () => void handleLogin(),
7089
+ children: busy === "login" ? t("signingIn") : t("signIn")
7090
+ }), flow === null && authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7091
+ className: "dsha-btn",
7092
+ disabled: busy !== null || status?.ownedByPlugin === false,
7093
+ title: status?.ownedByPlugin === false ? t("logoutOwnedByApp") : void 0,
7094
+ onClick: () => void handleLogout(),
7095
+ children: t("signOut")
7096
+ })]
7097
+ }),
7098
+ flow === null && authenticated && status?.ownedByPlugin === false && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7099
+ className: "dsha-muted",
7100
+ children: t("logoutOwnedByApp")
7101
+ })
7102
+ ]
7103
+ }),
7104
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
7105
+ className: "dsha-group",
7106
+ children: [
7107
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7108
+ className: "dsha-grouphead",
7109
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("connection") })
7110
+ }),
7111
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7112
+ className: "dsha-row",
7113
+ style: { marginBottom: 12 },
7114
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7115
+ className: "dsha-label",
7116
+ style: { fontWeight: 600 },
7117
+ children: t("enableProvider")
7118
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7119
+ type: "checkbox",
7120
+ "aria-label": t("enableProvider"),
7121
+ checked: status?.enabled !== false,
7122
+ disabled: busy !== null,
7123
+ onChange: (event) => void toggleEnabled(event.currentTarget.checked)
7124
+ })]
7125
+ }),
7126
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7127
+ className: "dsha-row",
7128
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7129
+ className: "dsha-label",
7130
+ children: t("provider")
7131
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7132
+ className: "dsha-value",
7133
+ children: `${MINIMAX_CODE_PROVIDER_NAME} · ${MINIMAX_CODE_PROVIDER_ID}`
7134
+ })]
7135
+ }),
7136
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7137
+ className: "dsha-row",
7138
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7139
+ className: "dsha-label",
7140
+ children: t("connectionState")
7141
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7142
+ className: "dsha-value",
7143
+ children: authenticated ? t("connected") : t("untested")
7144
+ })]
7145
+ }),
7146
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7147
+ className: "dsha-notice",
7148
+ children: status?.serving === false && status.conflict ? t("routeConflict").replace("{detail}", status.conflict) : t("routeOwned")
7149
+ }),
7150
+ connectionNotice !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7151
+ className: "dsha-muted",
7152
+ children: connectionNotice
7153
+ }),
7154
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7155
+ className: "dsha-actions",
7156
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7157
+ className: "dsha-btn",
7158
+ disabled: busy !== null || !authenticated,
7159
+ onClick: () => void handleTestConnection(),
7160
+ children: busy === "test" ? t("testingConnection") : t("testConnection")
7161
+ })
7162
+ })
7163
+ ]
7164
+ }),
7165
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
7166
+ className: "dsha-group",
7167
+ children: [
7168
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7169
+ className: "dsha-grouphead",
7170
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("modelsSection") })
7171
+ }),
7172
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7173
+ className: "dsha-muted",
7174
+ children: t("modelsHint").replace("{count}", String(models.length))
7175
+ }),
7176
+ models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7177
+ className: "dsha-empty",
7178
+ children: t("modelsUnavailable")
7179
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7180
+ className: "dsha-models",
7181
+ "aria-label": t("modelsSection"),
7182
+ children: models.map((model) => {
7183
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
7184
+ title: [
7185
+ model.id,
7186
+ thinkingLabel(model.thinking, t),
7187
+ ...model.description === null || model.description === "" ? [] : [model.description]
7188
+ ].join(" · "),
7189
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7190
+ type: "checkbox",
7191
+ checked: model.enabled,
7192
+ disabled: busy !== null,
7193
+ onChange: (event) => toggleModel(model.id, event.currentTarget.checked)
7194
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name })]
7195
+ }, model.id);
7196
+ })
7197
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7198
+ className: "dsha-actions",
7199
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7200
+ className: "dsha-btn",
7201
+ disabled: busy !== null,
7202
+ onClick: () => setAllModels(true),
7203
+ children: t("selectAll")
7204
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7205
+ className: "dsha-btn",
7206
+ disabled: busy !== null,
7207
+ onClick: () => setAllModels(false),
7208
+ children: t("unselectAll")
7209
+ })]
7210
+ })] })
7211
+ ]
7212
+ }),
7213
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
7214
+ className: "dsha-group",
7215
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7216
+ className: "dsha-grouphead",
7217
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("enhanced") })
7218
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7219
+ className: "dsha-pref-row",
7220
+ 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", {
7221
+ className: "dsha-muted",
7222
+ children: t("defaultReasoningEffortHint")
7223
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
7224
+ className: "dsha-select",
7225
+ "aria-label": t("defaultReasoningEffort"),
7226
+ value: status?.defaultReasoningEffort ?? "",
7227
+ disabled: busy !== null,
7228
+ onChange: (event) => {
7229
+ const value = event.currentTarget.value;
7230
+ handleUpdateEffort(value === "" ? null : value);
7231
+ },
7232
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7233
+ value: "",
7234
+ children: t("defaultEffortAuto")
7235
+ }), MINIMAX_CODE_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7236
+ value: effort,
7237
+ children: effort
7238
+ }, effort))]
7239
+ })]
7240
+ })]
7241
+ }),
7242
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
7243
+ className: "dsha-group",
7244
+ children: [
7245
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7246
+ className: "dsha-grouphead",
7247
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("contextWindowSection") })
7248
+ }),
7249
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7250
+ className: "dsha-muted",
7251
+ children: t("contextWindowHint")
7252
+ }),
7253
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7254
+ className: "dsha-context-settings",
7255
+ children: [
7256
+ contextModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7257
+ className: "dsha-muted",
7258
+ children: t("contextWindowNoneEnabled")
7259
+ }),
7260
+ contextModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7261
+ className: "dsha-context-row",
7262
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7263
+ title: model.id,
7264
+ children: [model.name, model.defaultContextWindow < model.contextWindow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7265
+ className: "dsha-model-meta",
7266
+ children: formatCapacity$1(model.contextWindow)
7267
+ })]
7268
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7269
+ className: "dsha-capacity-control",
7270
+ children: [
7271
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7272
+ type: "text",
7273
+ "aria-label": model.name + " " + t("contextWindowSection"),
7274
+ value: contextDrafts[model.id] ?? "",
7275
+ onChange: (event) => setContextDrafts({
7276
+ ...contextDrafts,
7277
+ [model.id]: event.currentTarget.value
7278
+ }),
7279
+ onKeyDown: (event) => {
7280
+ if (event.key === "Enter") handleSaveContextWindow(model.id);
7281
+ }
7282
+ }),
7283
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
7284
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7285
+ type: "button",
7286
+ className: "dsha-context-save",
7287
+ disabled: savingModel === model.id,
7288
+ onClick: () => void handleSaveContextWindow(model.id),
7289
+ children: savingModel === model.id ? t("saving") : t("save")
7290
+ }),
7291
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7292
+ type: "button",
7293
+ className: "dsha-context-save dsha-context-reset",
7294
+ "aria-label": model.name + " " + t("contextWindowReset"),
7295
+ disabled: savingModel === model.id || status?.contextWindowOverrides[model.id] === void 0,
7296
+ onClick: () => void handleResetContextWindow(model.id),
7297
+ children: t("contextWindowReset")
7298
+ })
7299
+ ]
7300
+ })]
7301
+ }, model.id)),
7302
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7303
+ className: "dsha-actions",
7304
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7305
+ className: "dsha-btn",
7306
+ disabled: busy !== null || overrideCount === 0,
7307
+ onClick: () => void handleResetAllContextWindows(),
7308
+ children: t("contextWindowResetAll")
7309
+ })
7310
+ })
7311
+ ]
7312
+ })
7313
+ ]
7314
+ }),
7315
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
7316
+ className: "dsha-group",
7317
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7318
+ className: "dsha-grouphead",
7319
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("quotaSection") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7320
+ className: "dsha-btn",
7321
+ disabled: busy !== null || !authenticated,
7322
+ onClick: () => void handleRefreshQuota(),
7323
+ children: busy === "quota" ? t("quotaRefreshing") : t("quotaRefresh")
7324
+ })]
7325
+ }), quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
7326
+ className: "dsha-notice dshm-quota-note",
7327
+ children: status?.quotaUnavailable === "credential-not-accepted" ? t("quotaNeedsApiKey") : status?.quotaUnavailable === "unreachable" ? t("quotaUnreachable") : t("quotaUnavailable")
7328
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7329
+ className: "dsha-quota-card",
7330
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7331
+ className: "dsha-quota-title",
7332
+ 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))) })]
7333
+ }), quotaWindows.map((window) => {
7334
+ const remaining = window.remainingPercent;
7335
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7336
+ className: "dsha-meter-wrap",
7337
+ children: [
7338
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7339
+ className: "dsha-meter-label",
7340
+ 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)))) })]
7341
+ }),
7342
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7343
+ className: `dsha-meter ${(remaining ?? 100) <= 10 ? "dsha-meter-cyan" : "dsha-meter-green"}`,
7344
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${Math.min(100, Math.max(0, Math.round(remaining ?? 100)))}%` } })
7345
+ }),
7346
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7347
+ className: "dsha-meter-meta",
7348
+ 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)) })]
7349
+ })
7350
+ ]
7351
+ }, window.key);
7352
+ })]
7353
+ })]
7354
+ }),
7355
+ error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7356
+ className: "dsha-error",
7357
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: error })
7358
+ })
7359
+ ]
7360
+ });
7361
+ }
7362
+ //#endregion
7363
+ //#region src/shared/workbuddy-contracts.ts
7364
+ /** Every level this route can name, in escalating order (the card's sort key). */
7365
+ const WORKBUDDY_REASONING_EFFORTS = [
7366
+ "minimal",
7367
+ "low",
7368
+ "medium",
7369
+ "high",
7370
+ "xhigh",
7371
+ "max"
7372
+ ];
7373
+ //#endregion
7374
+ //#region src/client/workbuddy/locales.ts
7375
+ const NS_WORKBUDDY = "dsh-workbuddy";
7376
+ const zh$1 = {
7377
+ title: "WorkBuddy",
7378
+ pageDesc: "复用本机 CodeBuddy 桌面端登录态,管理 WorkBuddy(CodeBuddy 订阅)模型、上下文窗口与额度。",
7379
+ account: "账号",
7380
+ noAccounts: "暂无账号。点击右上角「添加账号」完成浏览器授权,或登录 CodeBuddy 桌面端后重新扫描;桌面账号只能从本插件隐藏,绝不删除 CodeBuddy 的原凭据。",
7381
+ signedOut: "未找到凭据",
7382
+ nickname: "昵称",
7383
+ uin: "UIN",
7384
+ region: "区域",
7385
+ regionCn: "国区",
7386
+ regionIntl: "国际区",
7387
+ accountType: "账号类型",
7388
+ sourceFile: "凭据文件",
7389
+ authDirectory: "凭据目录",
7390
+ storage: "凭据存储",
7391
+ storageNotice: "桌面端账号仍读取 CodeBuddy 自己的凭据文件,插件不会删除这些文件;通过这里添加的账号保存在系统加密存储中(Windows DPAPI / macOS Keychain / Linux Secret Service),token 不进入浏览器。",
7392
+ routeUnreachable: "无法读取 WorkBuddy 设置路由",
7393
+ routeUnreachableHint: "浏览器里加载的插件版本可能比 Host 进程里运行的新(客户端资源是现读磁盘的,Host 只在启动时加载)。请重启 DSH,让两端来自同一份构建。",
7394
+ rescan: "重新扫描",
7395
+ rescanning: "扫描中...",
7396
+ accounts: "账号管理",
7397
+ addCnAccount: "添加国区账号",
7398
+ addIntlAccount: "添加国际区账号",
7399
+ authorizing: "授权中…",
7400
+ loginWaiting: "请在新打开的浏览器页面完成登录与授权。",
7401
+ loginFailed: "账号授权失败",
7402
+ encryptedStorage: "系统加密存储",
7403
+ hiddenAccount: "已隐藏",
7404
+ hideAccount: "从插件隐藏",
7405
+ restoreAccount: "恢复显示",
7406
+ deleteAccount: "删除账号",
7407
+ deleteConfirm: "确定删除这个插件托管的账号吗?加密存储中的登录凭据会被移除。",
7408
+ connection: "连接",
7409
+ provider: "Provider",
7410
+ providerValue: "WorkBuddy Subscription · workbuddy-subscription",
7411
+ connectionState: "连接状态",
7412
+ connected: "已连接",
7413
+ untested: "未测试",
7414
+ testConnection: "测试连接",
7415
+ testingConnection: "测试中...",
7416
+ latency: "延迟",
7417
+ routeOwned: "模型路由由本插件提供",
7418
+ routeConflict: "模型路由已被其他 Provider 占用:{detail}。请在 DSH 设置中移除重复的 Provider 配置后重试。",
7419
+ modelsSection: "模型",
7420
+ enableProvider: "启用此供应商",
7421
+ modelsHint: "勾选后模型才会出现在对话页的模型选择列表中;未勾选或关闭上方开关可在列表中隐藏该供应商。目录与上下文窗口来自订阅网关的模型目录,并按账号所在区域过滤——跨区调用会被上游拒绝。",
7422
+ refreshCatalog: "刷新模型目录",
7423
+ refreshingCatalog: "刷新中...",
7424
+ selectAll: "全选",
7425
+ unselectAll: "全不选",
6139
7426
  imageSupport: "图片",
6140
7427
  textOnly: "纯文本",
6141
7428
  regionBadge: "区域",
@@ -7327,6 +8614,10 @@ window.__ModuleLoader__.load({
7327
8614
  id: "workbuddy",
7328
8615
  label: "WorkBuddy"
7329
8616
  },
8617
+ {
8618
+ id: "minimax-code",
8619
+ label: "MiniMax Code"
8620
+ },
7330
8621
  {
7331
8622
  id: "claude",
7332
8623
  label: "Claude"
@@ -7341,6 +8632,31 @@ window.__ModuleLoader__.load({
7341
8632
  */
7342
8633
  function ProviderHubSection({ t, onModelChange, ...runtime }) {
7343
8634
  const [active, setActive] = (0, react.useState)("chatgpt");
8635
+ const tabStripRef = (0, react.useRef)(null);
8636
+ /**
8637
+ * Keep the selected tab inside the visible strip.
8638
+ *
8639
+ * The strip is one scrolling line, so a tab selected by keyboard (or restored
8640
+ * after a remount) can sit outside the viewport with no feedback about where
8641
+ * the selection went. `scrollIntoView` with `inline: 'nearest'` scrolls only
8642
+ * when the tab is actually out of view and keeps the change to the horizontal
8643
+ * axis, so it never nudges the settings page vertically.
8644
+ *
8645
+ * Guarded because jsdom (the DOM these tests run against) does not implement
8646
+ * `scrollIntoView`, and a settings page must not break in an environment that
8647
+ * lacks a scrolling method.
8648
+ */
8649
+ (0, react.useEffect)(() => {
8650
+ const strip = tabStripRef.current;
8651
+ if (strip === null) return;
8652
+ const selected = strip.querySelector("[role=\"tab\"][aria-selected=\"true\"]");
8653
+ if (selected === null) return;
8654
+ if (typeof selected.scrollIntoView !== "function") return;
8655
+ selected.scrollIntoView({
8656
+ inline: "nearest",
8657
+ block: "nearest"
8658
+ });
8659
+ }, [active]);
7344
8660
  const onTabKeyDown = (0, react.useCallback)((event) => {
7345
8661
  if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
7346
8662
  event.preventDefault();
@@ -7360,6 +8676,7 @@ window.__ModuleLoader__.load({
7360
8676
  children: t("hubTitle")
7361
8677
  }) }),
7362
8678
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8679
+ ref: tabStripRef,
7363
8680
  className: "dsh-codex-segments dsh-hub-tabs",
7364
8681
  role: "tablist",
7365
8682
  "aria-label": t("hubTitle"),
@@ -7389,6 +8706,7 @@ window.__ModuleLoader__.load({
7389
8706
  active === "command-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CommandCodeSection, { onModelChange }) : null,
7390
8707
  active === "kimi-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KimiCodeSection, { onModelChange }) : null,
7391
8708
  active === "workbuddy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkBuddySection, { onModelChange }) : null,
8709
+ active === "minimax-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MinimaxCodeSection, { onModelChange }) : null,
7392
8710
  active === "claude" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClaudeSection, { onModelChange }) : null
7393
8711
  ]
7394
8712
  })
@@ -7669,7 +8987,7 @@ window.__ModuleLoader__.load({
7669
8987
  //#endregion
7670
8988
  //#region src/client/styles.ts
7671
8989
  const PLUGIN_ID = "@eddyskywalker/dsh-chatgpt-subscription";
7672
- const STYLE_ID$4 = `${PLUGIN_ID}/main`;
8990
+ const STYLE_ID$5 = `${PLUGIN_ID}/main`;
7673
8991
  const CSS = `
7674
8992
  .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}
7675
8993
  .dsh-codex-page *{box-sizing:border-box}
@@ -7772,7 +9090,29 @@ window.__ModuleLoader__.load({
7772
9090
  .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}
7773
9091
  .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}
7774
9092
  .dsh-codex-image-failed{color:var(--dsw-alias-label-danger,#d94b4b)}
7775
- .dsh-hub-tabs{align-self:flex-start;max-width:100%}
9093
+ /* Seven provider tabs overflow a narrow settings pane. The shared
9094
+ .dsh-codex-segments rule pins flex-wrap to nowrap, so the strip originally ran
9095
+ past the pane edge with no way to reach the trailing tabs. Wrapping restored
9096
+ reachability but produced a ragged second row (five tabs, then two) whose right
9097
+ edge bore no relation to the first row's, which reads as a layout accident
9098
+ rather than a deliberate two-row control. The strip therefore stays on ONE line
9099
+ and scrolls horizontally.
9100
+ The scrollbar is deliberately thin but VISIBLE: it is the affordance that says
9101
+ more tabs exist, and hiding it would strand a mouse user, whose vertical wheel
9102
+ cannot scroll this row — the original bug in a new shape.
9103
+ Buttons are flex:none so the row scrolls instead of squashing labels. The
9104
+ padding is 4px, not the shared 3px, because overflow clips at the padding box:
9105
+ the focus ring is 2px wide with a 2px offset (4px beyond the button), so 3px
9106
+ would shave a pixel off it for keyboard users. scroll-padding keeps the same
9107
+ margin when a tab is scrolled into view by focus or by the active-tab effect
9108
+ in ProviderHubSection.
9109
+ Scoped to .dsh-hub-tabs so the ChatGPT provider-search group, which reuses
9110
+ .dsh-codex-segments, keeps its single-line layout. */
9111
+ .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}
9112
+ .dsh-hub-tabs button{flex:none}
9113
+ .dsh-hub-tabs::-webkit-scrollbar{height:6px}
9114
+ .dsh-hub-tabs::-webkit-scrollbar-track{background:transparent}
9115
+ .dsh-hub-tabs::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l2);border-radius:999px}
7776
9116
  @keyframes dsh-codex-pulse{0%,100%{opacity:.45}50%{opacity:.85}}
7777
9117
  @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}}
7778
9118
  @media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}
@@ -7798,25 +9138,25 @@ window.__ModuleLoader__.load({
7798
9138
  */
7799
9139
  function installStyles() {
7800
9140
  if (typeof document === "undefined") return () => void 0;
7801
- const existing = document.querySelector(`style[data-plugin-css="${STYLE_ID$4}"]`);
9141
+ const existing = document.querySelector(`style[data-plugin-css="${STYLE_ID$5}"]`);
7802
9142
  if (existing !== null) {
7803
9143
  if (existing.textContent !== CSS) existing.textContent = CSS;
7804
9144
  return () => void 0;
7805
9145
  }
7806
9146
  const element = document.createElement("style");
7807
9147
  element.dataset.plugin = PLUGIN_ID;
7808
- element.dataset.pluginCss = STYLE_ID$4;
9148
+ element.dataset.pluginCss = STYLE_ID$5;
7809
9149
  element.textContent = CSS;
7810
9150
  document.head.appendChild(element);
7811
9151
  return () => void 0;
7812
9152
  }
7813
9153
  //#endregion
7814
9154
  //#region src/client/antigravity/styles.ts
7815
- const STYLE_ID$3 = "dsh-antigravity-settings-style";
9155
+ const STYLE_ID$4 = "dsh-antigravity-settings-style";
7816
9156
  function installAntigravityStyles() {
7817
9157
  if (typeof document === "undefined" || document.getElementById("dsh-antigravity-settings-style")) return;
7818
9158
  const style = document.createElement("style");
7819
- style.id = STYLE_ID$3;
9159
+ style.id = STYLE_ID$4;
7820
9160
  style.textContent = `
7821
9161
  .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}
7822
9162
  .dsha-page *{box-sizing:border-box}
@@ -7960,7 +9300,7 @@ window.__ModuleLoader__.load({
7960
9300
  }
7961
9301
  }
7962
9302
  function AntigravityComposerQuota({ directory, loadModelDirectory }) {
7963
- const modelState = useStore$4(directory);
9303
+ const modelState = useStore$5(directory);
7964
9304
  const [status, setStatus] = (0, react.useState)(null);
7965
9305
  const [loading, setLoading] = (0, react.useState)(false);
7966
9306
  const mountedRef = (0, react.useRef)(false);
@@ -8017,7 +9357,7 @@ window.__ModuleLoader__.load({
8017
9357
  })]
8018
9358
  });
8019
9359
  }
8020
- function useStore$4(store) {
9360
+ function useStore$5(store) {
8021
9361
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
8022
9362
  }
8023
9363
  //#endregion
@@ -8050,7 +9390,7 @@ window.__ModuleLoader__.load({
8050
9390
  * remaining is 100 - used. A window at 0% used is the normal empty state and
8051
9391
  * grades as 'normal', not as an error.
8052
9392
  */
8053
- function selectBadgeFacts$3(status) {
9393
+ function selectBadgeFacts$4(status) {
8054
9394
  const quota = status?.quota;
8055
9395
  if (quota === null || quota === void 0) return {
8056
9396
  text: "—",
@@ -8079,7 +9419,7 @@ window.__ModuleLoader__.load({
8079
9419
  };
8080
9420
  }
8081
9421
  function ClaudeComposerQuota({ directory, loadModelDirectory }) {
8082
- const modelState = useStore$3(directory);
9422
+ const modelState = useStore$4(directory);
8083
9423
  const [status, setStatus] = (0, react.useState)(null);
8084
9424
  const [loading, setLoading] = (0, react.useState)(false);
8085
9425
  const mountedRef = (0, react.useRef)(false);
@@ -8113,7 +9453,7 @@ window.__ModuleLoader__.load({
8113
9453
  window.clearInterval(timer);
8114
9454
  };
8115
9455
  }, [fetchStatus, isClaude]);
8116
- const facts = (0, react.useMemo)(() => selectBadgeFacts$3(status), [status]);
9456
+ const facts = (0, react.useMemo)(() => selectBadgeFacts$4(status), [status]);
8117
9457
  if (!isClaude || !status?.authenticated || facts === null) return null;
8118
9458
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8119
9459
  className: "dsha-composer-quota",
@@ -8130,12 +9470,12 @@ window.__ModuleLoader__.load({
8130
9470
  })]
8131
9471
  });
8132
9472
  }
8133
- function useStore$3(store) {
9473
+ function useStore$4(store) {
8134
9474
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
8135
9475
  }
8136
9476
  //#endregion
8137
9477
  //#region src/client/claude/styles.ts
8138
- const STYLE_ID$2 = "dsh-claude-settings-style";
9478
+ const STYLE_ID$3 = "dsh-claude-settings-style";
8139
9479
  /**
8140
9480
  * Claude-only additions to the shared settings design system.
8141
9481
  *
@@ -8151,7 +9491,7 @@ window.__ModuleLoader__.load({
8151
9491
  function installClaudeStyles() {
8152
9492
  if (typeof document === "undefined" || document.getElementById("dsh-claude-settings-style")) return;
8153
9493
  const style = document.createElement("style");
8154
- style.id = STYLE_ID$2;
9494
+ style.id = STYLE_ID$3;
8155
9495
  style.textContent = `
8156
9496
  .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)}
8157
9497
  .dshcl-flow{border-bottom:0.5px solid var(--dsw-alias-border-l2);display:flex;flex-direction:column;gap:10px;padding:12px 0}
@@ -8186,7 +9526,7 @@ window.__ModuleLoader__.load({
8186
9526
  * A bounded usage window is the number a user actually spends down, so it wins
8187
9527
  * over a credit balance; the balance shows only when no window is reported.
8188
9528
  */
8189
- function selectBadgeFacts$2(status) {
9529
+ function selectBadgeFacts$3(status) {
8190
9530
  const quota = status?.quota;
8191
9531
  if (quota === null || quota === void 0) return {
8192
9532
  text: "—",
@@ -8228,7 +9568,7 @@ window.__ModuleLoader__.load({
8228
9568
  };
8229
9569
  }
8230
9570
  function CommandCodeComposerQuota({ directory, loadModelDirectory }) {
8231
- const modelState = useStore$2(directory);
9571
+ const modelState = useStore$3(directory);
8232
9572
  const [status, setStatus] = (0, react.useState)(null);
8233
9573
  const [loading, setLoading] = (0, react.useState)(false);
8234
9574
  const mountedRef = (0, react.useRef)(false);
@@ -8262,7 +9602,7 @@ window.__ModuleLoader__.load({
8262
9602
  window.clearInterval(timer);
8263
9603
  };
8264
9604
  }, [fetchStatus, isCommandCode]);
8265
- const facts = (0, react.useMemo)(() => selectBadgeFacts$2(status), [status]);
9605
+ const facts = (0, react.useMemo)(() => selectBadgeFacts$3(status), [status]);
8266
9606
  if (!isCommandCode || !status?.authenticated || facts === null) return null;
8267
9607
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8268
9608
  className: "dsha-composer-quota",
@@ -8279,7 +9619,7 @@ window.__ModuleLoader__.load({
8279
9619
  })]
8280
9620
  });
8281
9621
  }
8282
- function useStore$2(store) {
9622
+ function useStore$3(store) {
8283
9623
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
8284
9624
  }
8285
9625
  //#endregion
@@ -8304,7 +9644,7 @@ window.__ModuleLoader__.load({
8304
9644
  * blocks work soonest, so it wins over the longer pools; the 7-day allowance
8305
9645
  * shows only when no 5-hour window is reported.
8306
9646
  */
8307
- function selectBadgeFacts$1(status) {
9647
+ function selectBadgeFacts$2(status) {
8308
9648
  const quota = status?.quota;
8309
9649
  if (quota === null || quota === void 0) return {
8310
9650
  text: "—",
@@ -8336,7 +9676,7 @@ window.__ModuleLoader__.load({
8336
9676
  };
8337
9677
  }
8338
9678
  function KimiCodeComposerQuota({ directory, loadModelDirectory }) {
8339
- const modelState = useStore$1(directory);
9679
+ const modelState = useStore$2(directory);
8340
9680
  const [status, setStatus] = (0, react.useState)(null);
8341
9681
  const [loading, setLoading] = (0, react.useState)(false);
8342
9682
  const mountedRef = (0, react.useRef)(false);
@@ -8370,7 +9710,7 @@ window.__ModuleLoader__.load({
8370
9710
  window.clearInterval(timer);
8371
9711
  };
8372
9712
  }, [fetchStatus, isKimiCode]);
8373
- const facts = (0, react.useMemo)(() => selectBadgeFacts$1(status), [status]);
9713
+ const facts = (0, react.useMemo)(() => selectBadgeFacts$2(status), [status]);
8374
9714
  if (!isKimiCode || !status?.authenticated || facts === null) return null;
8375
9715
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8376
9716
  className: "dsha-composer-quota",
@@ -8387,12 +9727,12 @@ window.__ModuleLoader__.load({
8387
9727
  })]
8388
9728
  });
8389
9729
  }
8390
- function useStore$1(store) {
9730
+ function useStore$2(store) {
8391
9731
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
8392
9732
  }
8393
9733
  //#endregion
8394
9734
  //#region src/client/kimi-code/styles.ts
8395
- const STYLE_ID$1 = "dsh-kimi-code-settings-style";
9735
+ const STYLE_ID$2 = "dsh-kimi-code-settings-style";
8396
9736
  /**
8397
9737
  * Node the base control styles come from.
8398
9738
  *
@@ -8484,11 +9824,118 @@ window.__ModuleLoader__.load({
8484
9824
  function installKimiCodeStyles() {
8485
9825
  if (typeof document === "undefined" || document.getElementById("dsh-kimi-code-settings-style")) return;
8486
9826
  const style = document.createElement("style");
8487
- style.id = STYLE_ID$1;
9827
+ style.id = STYLE_ID$2;
8488
9828
  style.textContent = BASE;
8489
9829
  document.head.appendChild(style);
8490
9830
  }
8491
9831
  //#endregion
9832
+ //#region src/client/minimax-code/MinimaxCodeComposerQuota.tsx
9833
+ /**
9834
+ * Pick the badge facts for one status answer, or nothing at all.
9835
+ *
9836
+ * Quota is optional in the contract, and the usage read is allowed to fail (the
9837
+ * endpoint is undocumented and which host serves this subscription is
9838
+ * unmeasured), so a status without quota means the badge has nothing to say: it
9839
+ * is not rendered, rather than showing a placeholder that would read as a broken
9840
+ * meter. Callers must treat null as "hide the badge".
9841
+ */
9842
+ function selectBadgeFacts$1(status) {
9843
+ const quota = status?.quota;
9844
+ if (quota === void 0) return null;
9845
+ if (quota.usedPercent !== void 0 && Number.isFinite(quota.usedPercent)) {
9846
+ const remaining = Math.max(0, Math.round(100 - quota.usedPercent));
9847
+ return {
9848
+ text: `${remaining}%`,
9849
+ tooltip: `[MiniMax Code] ${quota.label}: ${remaining}% left`,
9850
+ level: remaining <= 5 ? "danger" : remaining <= 20 ? "warning" : "normal"
9851
+ };
9852
+ }
9853
+ return {
9854
+ text: quota.label,
9855
+ tooltip: `[MiniMax Code] ${quota.label}`,
9856
+ level: "normal"
9857
+ };
9858
+ }
9859
+ function MinimaxCodeComposerQuota({ t, directory, loadModelDirectory }) {
9860
+ const modelState = useStore$1(directory);
9861
+ const [status, setStatus] = (0, react.useState)(null);
9862
+ const [loading, setLoading] = (0, react.useState)(false);
9863
+ const mountedRef = (0, react.useRef)(false);
9864
+ const isMinimaxCode = modelState.current?.provider === MINIMAX_CODE_PROVIDER_ID;
9865
+ (0, react.useEffect)(() => {
9866
+ loadModelDirectory();
9867
+ }, [loadModelDirectory]);
9868
+ (0, react.useEffect)(() => {
9869
+ mountedRef.current = true;
9870
+ return () => {
9871
+ mountedRef.current = false;
9872
+ };
9873
+ }, []);
9874
+ const fetchStatus = (0, react.useCallback)(async () => {
9875
+ if (!mountedRef.current) return;
9876
+ setLoading(true);
9877
+ try {
9878
+ const data = await get("/quota");
9879
+ if (mountedRef.current) setStatus(data);
9880
+ } catch {} finally {
9881
+ if (mountedRef.current) setLoading(false);
9882
+ }
9883
+ }, []);
9884
+ (0, react.useEffect)(() => {
9885
+ if (!isMinimaxCode) return;
9886
+ fetchStatus();
9887
+ const timer = window.setInterval(() => {
9888
+ if (document.visibilityState === "visible") fetchStatus();
9889
+ }, 6e4);
9890
+ return () => {
9891
+ window.clearInterval(timer);
9892
+ };
9893
+ }, [fetchStatus, isMinimaxCode]);
9894
+ const facts = (0, react.useMemo)(() => selectBadgeFacts$1(status), [status]);
9895
+ if (!isMinimaxCode || !status?.authenticated || facts === null) return null;
9896
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
9897
+ className: "dsha-composer-quota",
9898
+ "data-level": facts.level,
9899
+ title: facts.tooltip,
9900
+ "aria-label": facts.tooltip,
9901
+ onClick: () => void fetchStatus(),
9902
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
9903
+ className: "dsha-composer-quota-label",
9904
+ children: t("composerLabel")
9905
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
9906
+ className: "dsha-composer-quota-val",
9907
+ children: loading ? "…" : facts.text
9908
+ })]
9909
+ });
9910
+ }
9911
+ function useStore$1(store) {
9912
+ return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
9913
+ }
9914
+ //#endregion
9915
+ //#region src/client/minimax-code/styles.ts
9916
+ const STYLE_ID$1 = "dsh-minimax-code-settings-style";
9917
+ /**
9918
+ * MiniMax Code-only additions to the shared settings design system.
9919
+ *
9920
+ * The base control styles (.dsha-page, .dsha-group, .dsha-row, .dsha-models,
9921
+ * the device-code box, the meter, the composer badge, ...) come from the
9922
+ * stylesheet the sibling routes install, in the same order the client installs
9923
+ * them, so this file declares only what stays unique to this card: the mono
9924
+ * credential path and the model-name list.
9925
+ */
9926
+ function installMinimaxCodeStyles() {
9927
+ if (typeof document === "undefined" || document.getElementById("dsh-minimax-code-settings-style")) return;
9928
+ const style = document.createElement("style");
9929
+ style.id = STYLE_ID$1;
9930
+ style.textContent = `
9931
+ .dshm-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px}
9932
+ .dshm-model-list{display:flex;flex-wrap:wrap;gap:7px;padding-top:8px}
9933
+ .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}
9934
+ .dshm-quota-note{margin-top:12px}
9935
+ `;
9936
+ document.head.append(style);
9937
+ }
9938
+ //#endregion
8492
9939
  //#region src/client/workbuddy/WorkBuddyComposerQuota.tsx
8493
9940
  const API = "/workbuddy/api";
8494
9941
  async function fetchApi(path, options) {
@@ -8963,22 +10410,27 @@ window.__ModuleLoader__.load({
8963
10410
  function apply(ctx) {
8964
10411
  ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-chatgpt-subscription: dictionaries");
8965
10412
  ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
8966
- ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$5), "dsh-antigravity: dictionaries");
10413
+ ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$6), "dsh-antigravity: dictionaries");
8967
10414
  ctx.effect(() => {
8968
10415
  installAntigravityStyles();
8969
10416
  return () => {};
8970
10417
  }, "dsh-antigravity: styles");
8971
- ctx.effect(() => ctx.locale.register(NS_CLAUDE, dictionaries$3), "dsh-claude: dictionaries");
10418
+ ctx.effect(() => ctx.locale.register(NS_CLAUDE, dictionaries$4), "dsh-claude: dictionaries");
8972
10419
  ctx.effect(() => {
8973
10420
  installClaudeStyles();
8974
10421
  return () => {};
8975
10422
  }, "dsh-claude: styles");
8976
- ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$4), "dsh-command-code: dictionaries");
8977
- ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$2), "dsh-kimi-code: dictionaries");
10423
+ ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$5), "dsh-command-code: dictionaries");
10424
+ ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$3), "dsh-kimi-code: dictionaries");
8978
10425
  ctx.effect(() => {
8979
10426
  installKimiCodeStyles();
8980
10427
  return () => {};
8981
10428
  }, "dsh-kimi-code: styles");
10429
+ ctx.effect(() => ctx.locale.register(NS_MINIMAX_CODE, dictionaries$2), "dsh-minimax-code: dictionaries");
10430
+ ctx.effect(() => {
10431
+ installMinimaxCodeStyles();
10432
+ return () => {};
10433
+ }, "dsh-minimax-code: styles");
8982
10434
  ctx.effect(() => ctx.locale.register(NS_WORKBUDDY, dictionaries$1), "dsh-workbuddy: dictionaries");
8983
10435
  ctx.effect(() => {
8984
10436
  installWorkBuddyStyles();
@@ -9086,6 +10538,21 @@ window.__ModuleLoader__.load({
9086
10538
  };
9087
10539
  }
9088
10540
  }, WorkBuddyComposerQuota));
10541
+ ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
10542
+ name: "conversation.input.right",
10543
+ id: "minimax-code-quota",
10544
+ order: 40,
10545
+ locale: NS_MINIMAX_CODE,
10546
+ inject: (sessionId) => {
10547
+ const directory = ctx.modelDirectories.directoryFor(sessionId);
10548
+ return {
10549
+ directory: directory.store,
10550
+ loadModelDirectory: () => {
10551
+ directory.load().catch(() => void 0);
10552
+ }
10553
+ };
10554
+ }
10555
+ }, MinimaxCodeComposerQuota));
9089
10556
  ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
9090
10557
  name: "conversation.input.right",
9091
10558
  id: "claude-quota",