@eddyskywalker/dsh-chatgpt-subscription 0.8.0-alpha.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +65 -0
  3. package/lib/client.js +2051 -456
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +4762 -1711
  6. package/lib/types/client/CodexSubscriptionSection.d.ts.map +1 -1
  7. package/lib/types/client/ProviderHubSection.d.ts.map +1 -1
  8. package/lib/types/client/antigravity/AntigravitySection.d.ts.map +1 -1
  9. package/lib/types/client/antigravity/locales.d.ts +14 -2
  10. package/lib/types/client/antigravity/locales.d.ts.map +1 -1
  11. package/lib/types/client/antigravity/styles.d.ts.map +1 -1
  12. package/lib/types/client/command-code/CommandCodeSection.d.ts.map +1 -1
  13. package/lib/types/client/command-code/locales.d.ts +14 -2
  14. package/lib/types/client/command-code/locales.d.ts.map +1 -1
  15. package/lib/types/client/index.d.ts +1 -0
  16. package/lib/types/client/index.d.ts.map +1 -1
  17. package/lib/types/client/kimi-code/KimiCodeSection.d.ts.map +1 -1
  18. package/lib/types/client/kimi-code/locales.d.ts +14 -2
  19. package/lib/types/client/kimi-code/locales.d.ts.map +1 -1
  20. package/lib/types/client/kimi-code/styles.d.ts.map +1 -1
  21. package/lib/types/client/locales.d.ts +13 -5
  22. package/lib/types/client/locales.d.ts.map +1 -1
  23. package/lib/types/client/workbuddy/WorkBuddySection.d.ts.map +1 -1
  24. package/lib/types/client/workbuddy/locales.d.ts +84 -0
  25. package/lib/types/client/workbuddy/locales.d.ts.map +1 -1
  26. package/lib/types/client/zhipu/ZhipuComposerQuota.d.ts +26 -0
  27. package/lib/types/client/zhipu/ZhipuComposerQuota.d.ts.map +1 -0
  28. package/lib/types/client/zhipu/ZhipuSection.d.ts +11 -0
  29. package/lib/types/client/zhipu/ZhipuSection.d.ts.map +1 -0
  30. package/lib/types/client/zhipu/locales.d.ts +275 -0
  31. package/lib/types/client/zhipu/locales.d.ts.map +1 -0
  32. package/lib/types/client/zhipu/styles.d.ts +12 -0
  33. package/lib/types/client/zhipu/styles.d.ts.map +1 -0
  34. package/lib/types/host/antigravity/token-store.d.ts +5 -2
  35. package/lib/types/host/antigravity/token-store.d.ts.map +1 -1
  36. package/lib/types/host/command-code/routes.d.ts.map +1 -1
  37. package/lib/types/host/command-code/token-store.d.ts +5 -2
  38. package/lib/types/host/command-code/token-store.d.ts.map +1 -1
  39. package/lib/types/host/common/context-window-overrides.d.ts +12 -0
  40. package/lib/types/host/common/context-window-overrides.d.ts.map +1 -0
  41. package/lib/types/host/kimi-code/routes.d.ts.map +1 -1
  42. package/lib/types/host/kimi-code/token-store.d.ts +5 -2
  43. package/lib/types/host/kimi-code/token-store.d.ts.map +1 -1
  44. package/lib/types/host/preferences.d.ts.map +1 -1
  45. package/lib/types/host/routes.d.ts.map +1 -1
  46. package/lib/types/host/workbuddy/checkin.d.ts +134 -0
  47. package/lib/types/host/workbuddy/checkin.d.ts.map +1 -0
  48. package/lib/types/host/workbuddy/routes.d.ts +3 -0
  49. package/lib/types/host/workbuddy/routes.d.ts.map +1 -1
  50. package/lib/types/host/workbuddy/token-store.d.ts +29 -3
  51. package/lib/types/host/workbuddy/token-store.d.ts.map +1 -1
  52. package/lib/types/host/zhipu/account-pool.d.ts +43 -0
  53. package/lib/types/host/zhipu/account-pool.d.ts.map +1 -0
  54. package/lib/types/host/zhipu/adapter.d.ts +93 -0
  55. package/lib/types/host/zhipu/adapter.d.ts.map +1 -0
  56. package/lib/types/host/zhipu/client.d.ts +153 -0
  57. package/lib/types/host/zhipu/client.d.ts.map +1 -0
  58. package/lib/types/host/zhipu/mapper.d.ts +111 -0
  59. package/lib/types/host/zhipu/mapper.d.ts.map +1 -0
  60. package/lib/types/host/zhipu/model-catalog.d.ts +73 -0
  61. package/lib/types/host/zhipu/model-catalog.d.ts.map +1 -0
  62. package/lib/types/host/zhipu/routes.d.ts +33 -0
  63. package/lib/types/host/zhipu/routes.d.ts.map +1 -0
  64. package/lib/types/host/zhipu/token-store.d.ts +112 -0
  65. package/lib/types/host/zhipu/token-store.d.ts.map +1 -0
  66. package/lib/types/host/zhipu/types.d.ts +125 -0
  67. package/lib/types/host/zhipu/types.d.ts.map +1 -0
  68. package/lib/types/index.d.ts +8 -0
  69. package/lib/types/index.d.ts.map +1 -1
  70. package/lib/types/shared/antigravity-contracts.d.ts +2 -1
  71. package/lib/types/shared/antigravity-contracts.d.ts.map +1 -1
  72. package/lib/types/shared/command-code-contracts.d.ts +2 -1
  73. package/lib/types/shared/command-code-contracts.d.ts.map +1 -1
  74. package/lib/types/shared/contracts.d.ts +5 -9
  75. package/lib/types/shared/contracts.d.ts.map +1 -1
  76. package/lib/types/shared/kimi-code-contracts.d.ts +2 -1
  77. package/lib/types/shared/kimi-code-contracts.d.ts.map +1 -1
  78. package/lib/types/shared/model-catalog.d.ts +6 -4
  79. package/lib/types/shared/model-catalog.d.ts.map +1 -1
  80. package/lib/types/shared/preferences.d.ts.map +1 -1
  81. package/lib/types/shared/workbuddy-contracts.d.ts +42 -1
  82. package/lib/types/shared/workbuddy-contracts.d.ts.map +1 -1
  83. package/lib/types/shared/zhipu-contracts.d.ts +156 -0
  84. package/lib/types/shared/zhipu-contracts.d.ts.map +1 -0
  85. package/package.json +31 -31
package/lib/client.js CHANGED
@@ -56,7 +56,7 @@ window.__ModuleLoader__.load({
56
56
  //#endregion
57
57
  //#region src/client/CodexComposerQuota.tsx
58
58
  function CodexComposerQuota({ api, directory, loadModelDirectory, t }) {
59
- const modelState = useStore$4(directory);
59
+ const modelState = useStore$5(directory);
60
60
  const [status, setStatus] = (0, react.useState)(null);
61
61
  const [loading, setLoading] = (0, react.useState)(false);
62
62
  const mountedRef = (0, react.useRef)(false);
@@ -103,7 +103,7 @@ window.__ModuleLoader__.load({
103
103
  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
104
  });
105
105
  }
106
- function useStore$4(store) {
106
+ function useStore$5(store) {
107
107
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
108
108
  }
109
109
  function formatPercent$1(value) {
@@ -179,7 +179,7 @@ window.__ModuleLoader__.load({
179
179
  });
180
180
  }
181
181
  function promptFromBlock(block) {
182
- const raw = "kind" in block ? block.call?.argsRaw : block.argsRaw;
182
+ const raw = "kind" in block ? block.call?.argsRaw : dispatchedArgsRaw(block);
183
183
  if (typeof raw !== "string" || raw.trim() === "") return null;
184
184
  try {
185
185
  const value = JSON.parse(raw);
@@ -188,6 +188,16 @@ window.__ModuleLoader__.load({
188
188
  return null;
189
189
  }
190
190
  }
191
+ /**
192
+ * Arguments of a dispatched call that has no result yet.
193
+ *
194
+ * Harness 0.1.7-rc.1 dispatches a view as soon as its call starts *preparing*,
195
+ * before the arguments exist, so the preparing shape carries no `argsRaw` at
196
+ * all. Older generations only ever sent the dispatched shape.
197
+ */
198
+ function dispatchedArgsRaw(block) {
199
+ return "argsRaw" in block ? block.argsRaw : void 0;
200
+ }
191
201
  function imageBlocks(blocks) {
192
202
  const result = [];
193
203
  for (const block of blocks) {
@@ -316,14 +326,11 @@ window.__ModuleLoader__.load({
316
326
  "gpt-5.6-luna"
317
327
  ];
318
328
  const DEFAULT_CODEX_MODEL = CODEX_MODEL_CATALOG[0];
319
- const CONFIGURABLE_CONTEXT_MODEL_IDS = [
320
- "gpt-6-astra",
321
- "gpt-6-sol",
322
- "gpt-6-luna",
323
- "gpt-5.6-sol",
324
- "gpt-5.6-terra",
325
- "gpt-5.6-luna"
326
- ];
329
+ /**
330
+ * Upper bound for one model's context window override. The Codex subscription
331
+ * caps the whole GPT-6 family at 872K and everything older at 1M, so a model's
332
+ * catalog default is where the number starts, not where it has to stay.
333
+ */
327
334
  function contextWindowLimitForModel(model) {
328
335
  return resolveCodexCatalogEntry(model).reasoningProfile === "gpt-6" ? GPT_6_MAX_CONTEXT_WINDOW : GPT_56_MAX_CONTEXT_WINDOW;
329
336
  }
@@ -837,6 +844,22 @@ window.__ModuleLoader__.load({
837
844
  [model]: String(parsed)
838
845
  }));
839
846
  };
847
+ /** Drop one model's override; the row falls back to the catalog value. */
848
+ const resetContextWindow = async (model) => {
849
+ await updatePreferences({ contextWindowOverrides: { [model]: null } });
850
+ setContextDrafts((drafts) => ({
851
+ ...drafts,
852
+ [model]: formatCapacity$5(resolveCodexCatalogEntry(model).contextWindow)
853
+ }));
854
+ };
855
+ /** Clear every stored override, including models the picker no longer shows. */
856
+ const resetAllContextWindows = async () => {
857
+ const models = Object.keys(status?.preferences.contextWindowOverrides ?? {});
858
+ if (models.length === 0) return;
859
+ if (!window.confirm(t("contextWindowResetAllConfirm"))) return;
860
+ await updatePreferences({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) });
861
+ setContextDrafts({});
862
+ };
840
863
  const updateCustomProxyUrl = async () => {
841
864
  const draft = customProxyDraft?.trim();
842
865
  await updatePreferences({ customProxyUrl: draft ? draft : null });
@@ -925,6 +948,8 @@ window.__ModuleLoader__.load({
925
948
  const storage = status?.storage;
926
949
  const login = status?.login;
927
950
  const visibleModelIds = preferences?.visibleModelIds ?? DEFAULT_VISIBLE_CODEX_MODEL_IDS;
951
+ const contextModels = CODEX_MODEL_CATALOG.filter((entry) => visibleModelIds.some((id) => id === entry.id));
952
+ const overrideCount = Object.keys(preferences?.contextWindowOverrides ?? {}).length;
928
953
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
929
954
  className: "dsha-page",
930
955
  "aria-labelledby": "dsh-codex-title",
@@ -1038,7 +1063,7 @@ window.__ModuleLoader__.load({
1038
1063
  }),
1039
1064
  connection !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoRow, {
1040
1065
  label: t("latency"),
1041
- value: `${connection.latencyMs} ms · ${formatDate$3(connection.checkedAt)}`
1066
+ value: `${connection.latencyMs} ms · ${formatDate$4(connection.checkedAt)}`
1042
1067
  }) : null,
1043
1068
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1044
1069
  className: "dsha-muted dsha-models-hint",
@@ -1289,58 +1314,83 @@ window.__ModuleLoader__.load({
1289
1314
  }),
1290
1315
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1291
1316
  className: "dsha-context-settings",
1292
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("contextWindows") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1293
- className: "dsha-muted",
1294
- children: t("contextWindowsHint")
1295
- })] }), CONFIGURABLE_CONTEXT_MODEL_IDS.map((model) => {
1296
- const entry = resolveCodexCatalogEntry(model);
1297
- const fallback = preferences?.contextWindowOverrides?.[model] ?? entry.contextWindow;
1298
- const draft = contextDrafts[model];
1299
- const parsedDraft = draft === void 0 ? fallback : parseCapacity(draft, contextWindowLimitForModel(model));
1300
- const dirty = draft !== void 0 && parsedDraft !== fallback;
1301
- const inputId = `dsh-codex-context-${model}`;
1302
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1303
- className: "dsha-context-row",
1304
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1305
- htmlFor: inputId,
1306
- children: entry.name
1307
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1308
- className: "dsha-capacity-control",
1309
- children: [
1310
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1311
- id: inputId,
1312
- type: "text",
1313
- inputMode: "numeric",
1314
- value: draft ?? formatCapacity$4(fallback),
1315
- disabled: busy !== null,
1316
- "aria-label": entry.name + " " + t("contextWindow"),
1317
- onChange: (event) => {
1318
- const value = event.currentTarget.value;
1319
- setContextDrafts((drafts) => ({
1320
- ...drafts,
1321
- [model]: value
1322
- }));
1323
- },
1324
- onKeyDown: (event) => {
1325
- if (event.key !== "Enter" || !dirty) return;
1326
- event.preventDefault();
1327
- updateContextWindow(model);
1328
- }
1329
- }),
1330
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
1331
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1332
- className: "dsha-context-save",
1333
- type: "button",
1334
- "data-model": model,
1335
- "aria-label": entry.name + " " + t("saveContextWindow"),
1336
- disabled: busy !== null || !dirty,
1337
- onClick: () => void updateContextWindow(model),
1338
- children: t("save")
1339
- })
1340
- ]
1341
- })]
1342
- }, model);
1343
- })]
1317
+ children: [
1318
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("contextWindows") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1319
+ className: "dsha-muted",
1320
+ children: t("contextWindowsHint")
1321
+ })] }),
1322
+ contextModels.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1323
+ className: "dsha-muted",
1324
+ children: t("contextWindowsNoneEnabled")
1325
+ }) : null,
1326
+ contextModels.map((entry) => {
1327
+ const model = entry.id;
1328
+ const fallback = preferences?.contextWindowOverrides?.[model] ?? entry.contextWindow;
1329
+ const draft = contextDrafts[model];
1330
+ const parsedDraft = draft === void 0 ? fallback : parseCapacity(draft, contextWindowLimitForModel(model));
1331
+ const dirty = draft !== void 0 && parsedDraft !== fallback;
1332
+ const overridden = preferences?.contextWindowOverrides?.[model] !== void 0;
1333
+ const inputId = `dsh-codex-context-${model}`;
1334
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1335
+ className: "dsha-context-row",
1336
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1337
+ htmlFor: inputId,
1338
+ children: entry.name
1339
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1340
+ className: "dsha-capacity-control",
1341
+ children: [
1342
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1343
+ id: inputId,
1344
+ type: "text",
1345
+ inputMode: "numeric",
1346
+ value: draft ?? formatCapacity$5(fallback),
1347
+ disabled: busy !== null,
1348
+ "aria-label": entry.name + " " + t("contextWindow"),
1349
+ onChange: (event) => {
1350
+ const value = event.currentTarget.value;
1351
+ setContextDrafts((drafts) => ({
1352
+ ...drafts,
1353
+ [model]: value
1354
+ }));
1355
+ },
1356
+ onKeyDown: (event) => {
1357
+ if (event.key !== "Enter" || !dirty) return;
1358
+ event.preventDefault();
1359
+ updateContextWindow(model);
1360
+ }
1361
+ }),
1362
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
1363
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1364
+ className: "dsha-context-save",
1365
+ type: "button",
1366
+ "data-model": model,
1367
+ "aria-label": entry.name + " " + t("saveContextWindow"),
1368
+ disabled: busy !== null || !dirty,
1369
+ onClick: () => void updateContextWindow(model),
1370
+ children: t("save")
1371
+ }),
1372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1373
+ className: "dsha-context-save dsha-context-reset",
1374
+ type: "button",
1375
+ "data-reset-model": model,
1376
+ "aria-label": entry.name + " " + t("contextWindowReset"),
1377
+ disabled: busy !== null || !overridden,
1378
+ onClick: () => void resetContextWindow(model),
1379
+ children: t("contextWindowReset")
1380
+ })
1381
+ ]
1382
+ })]
1383
+ }, model);
1384
+ }),
1385
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1386
+ className: "dsha-actions",
1387
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
1388
+ disabled: busy !== null || overrideCount === 0,
1389
+ onClick: resetAllContextWindows,
1390
+ children: t("contextWindowResetAll")
1391
+ })
1392
+ })
1393
+ ]
1344
1394
  }),
1345
1395
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1346
1396
  className: "dsh-codex-check",
@@ -1425,7 +1475,7 @@ window.__ModuleLoader__.load({
1425
1475
  children: [
1426
1476
  t("updated"),
1427
1477
  ": ",
1428
- formatDate$3(quota.fetchedAt)
1478
+ formatDate$4(quota.fetchedAt)
1429
1479
  ]
1430
1480
  }) : null
1431
1481
  ]
@@ -1517,7 +1567,7 @@ window.__ModuleLoader__.load({
1517
1567
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [
1518
1568
  t("resetCreditExpires"),
1519
1569
  ": ",
1520
- resetCredits.expiresAt == null ? t("unknown") : formatReset$3(resetCredits.expiresAt)
1570
+ resetCredits.expiresAt == null ? t("unknown") : formatReset$4(resetCredits.expiresAt)
1521
1571
  ] })
1522
1572
  ]
1523
1573
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
@@ -1550,7 +1600,7 @@ window.__ModuleLoader__.load({
1550
1600
  }),
1551
1601
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1552
1602
  className: "dsh-codex-meter-meta",
1553
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: percent >= 100 ? `${t("exhausted")} · ${formatPercent(remaining)} ${t("remaining")}` : `${formatPercent(percent)} ${t("used")} · ${formatPercent(remaining)} ${t("remaining")}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window?.resetsAt == null ? "—" : `${t("resets")}: ${formatReset$3(window.resetsAt)}` })]
1603
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: percent >= 100 ? `${t("exhausted")} · ${formatPercent(remaining)} ${t("remaining")}` : `${formatPercent(percent)} ${t("used")} · ${formatPercent(remaining)} ${t("remaining")}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window?.resetsAt == null ? "—" : `${t("resets")}: ${formatReset$4(window.resetsAt)}` })]
1554
1604
  })
1555
1605
  ]
1556
1606
  });
@@ -1576,7 +1626,7 @@ window.__ModuleLoader__.load({
1576
1626
  return `${value} ${t("limitWindow")}`;
1577
1627
  }
1578
1628
  }
1579
- function parsePositiveCapacity$4(value) {
1629
+ function parsePositiveCapacity$5(value) {
1580
1630
  const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
1581
1631
  if (matched === null) return null;
1582
1632
  const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
@@ -1584,10 +1634,10 @@ window.__ModuleLoader__.load({
1584
1634
  return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
1585
1635
  }
1586
1636
  function parseCapacity(value, maxContextWindow = GPT_56_MAX_CONTEXT_WINDOW) {
1587
- const parsed = parsePositiveCapacity$4(value);
1637
+ const parsed = parsePositiveCapacity$5(value);
1588
1638
  return parsed !== null && parsed <= maxContextWindow ? parsed : null;
1589
1639
  }
1590
- function formatCapacity$4(value) {
1640
+ function formatCapacity$5(value) {
1591
1641
  if (value % 1e3 === 0) return `${value / 1e3}K`;
1592
1642
  return String(value);
1593
1643
  }
@@ -1604,11 +1654,11 @@ window.__ModuleLoader__.load({
1604
1654
  limit.remainingPercent !== null && limit.remainingPercent !== void 0 ? `${formatPercent(limit.remainingPercent)} ${t("remaining")}` : null,
1605
1655
  limit.limit !== null && limit.limit !== void 0 ? `${t("limit")}: ${limit.limit}` : null,
1606
1656
  limit.used !== null && limit.used !== void 0 ? `${t("used")}: ${limit.used}` : null,
1607
- limit.resetsAt !== null && limit.resetsAt !== void 0 ? `${t("resets")}: ${formatReset$3(limit.resetsAt)}` : null
1657
+ limit.resetsAt !== null && limit.resetsAt !== void 0 ? `${t("resets")}: ${formatReset$4(limit.resetsAt)}` : null
1608
1658
  ].filter((part) => part !== null);
1609
1659
  return parts.length > 0 ? parts.join(" · ") : t("unknown");
1610
1660
  }
1611
- function formatDate$3(seconds) {
1661
+ function formatDate$4(seconds) {
1612
1662
  if (seconds === void 0 || seconds === null || typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) return "—";
1613
1663
  const ms = seconds > 1e10 ? seconds : seconds * 1e3;
1614
1664
  try {
@@ -1620,10 +1670,10 @@ window.__ModuleLoader__.load({
1620
1670
  return "—";
1621
1671
  }
1622
1672
  }
1623
- function formatReset$3(seconds) {
1673
+ function formatReset$4(seconds) {
1624
1674
  if (seconds === void 0 || seconds === null || typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) return "—";
1625
1675
  const ms = seconds > 1e10 ? seconds : seconds * 1e3;
1626
- const absolute = formatDate$3(seconds);
1676
+ const absolute = formatDate$4(seconds);
1627
1677
  const diff = ms - Date.now();
1628
1678
  const abs = Math.abs(diff);
1629
1679
  const [amount, unit] = abs >= 864e5 ? [Math.round(diff / 864e5), "day"] : abs >= 36e5 ? [Math.round(diff / 36e5), "hour"] : [Math.round(diff / 6e4), "minute"];
@@ -1639,7 +1689,7 @@ window.__ModuleLoader__.load({
1639
1689
  //#endregion
1640
1690
  //#region src/client/antigravity/locales.ts
1641
1691
  const NS_ANTIGRAVITY = "dsh-antigravity";
1642
- const zh$4 = {
1692
+ const zh$5 = {
1643
1693
  ...accountPoolZh,
1644
1694
  title: "Antigravity",
1645
1695
  pageDesc: "登录 Google Antigravity / Cloud Code Assist,并查看当前账号的共享额度。",
@@ -1685,6 +1735,10 @@ window.__ModuleLoader__.load({
1685
1735
  defaultEffortAuto: "使用 Provider 默认值",
1686
1736
  contextWindowSection: "模型上下文窗口",
1687
1737
  contextWindowHint: "默认按模型标准;可选应用最高容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
1738
+ contextWindowReset: "恢复默认",
1739
+ contextWindowResetAll: "全部恢复默认",
1740
+ contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
1741
+ contextWindowNoneEnabled: "还没有勾选任何模型。在上方勾选后,这里会出现该模型的上下文窗口设置。",
1688
1742
  save: "保存",
1689
1743
  saved: "已保存",
1690
1744
  saving: "保存中...",
@@ -1705,7 +1759,7 @@ window.__ModuleLoader__.load({
1705
1759
  loginFailed: "登录失败",
1706
1760
  tokens: "tokens"
1707
1761
  };
1708
- const en$4 = {
1762
+ const en$5 = {
1709
1763
  ...accountPoolEn,
1710
1764
  title: "Antigravity",
1711
1765
  pageDesc: "Sign in to Google Antigravity / Cloud Code Assist and view shared quotas.",
@@ -1751,6 +1805,10 @@ window.__ModuleLoader__.load({
1751
1805
  defaultEffortAuto: "Use Provider default",
1752
1806
  contextWindowSection: "Model Context Window",
1753
1807
  contextWindowHint: "Defaults to model specification; configure custom capacity used by DSH for compaction and overflow judgments (e.g., 1M, 512K, 200K).",
1808
+ contextWindowReset: "Restore default",
1809
+ contextWindowResetAll: "Restore all defaults",
1810
+ contextWindowResetAllConfirm: "Restore every changed model context window to its default?",
1811
+ contextWindowNoneEnabled: "No model is checked yet. Check one above and its context window setting appears here.",
1754
1812
  save: "Save",
1755
1813
  saved: "Saved",
1756
1814
  saving: "Saving...",
@@ -1771,17 +1829,17 @@ window.__ModuleLoader__.load({
1771
1829
  loginFailed: "Login failed",
1772
1830
  tokens: "tokens"
1773
1831
  };
1774
- const dictionaries$4 = {
1775
- zh: zh$4,
1776
- "zh-CN": zh$4,
1777
- en: en$4,
1778
- "en-US": en$4
1832
+ const dictionaries$5 = {
1833
+ zh: zh$5,
1834
+ "zh-CN": zh$5,
1835
+ en: en$5,
1836
+ "en-US": en$5
1779
1837
  };
1780
1838
  //#endregion
1781
1839
  //#region src/client/antigravity/AntigravitySection.tsx
1782
- const API$7 = "/antigravity/api";
1783
- async function fetchApi$7(path, options) {
1784
- const res = await fetch(`${API$7}${path}`, {
1840
+ const API$9 = "/antigravity/api";
1841
+ async function fetchApi$9(path, options) {
1842
+ const res = await fetch(`${API$9}${path}`, {
1785
1843
  ...options,
1786
1844
  headers: {
1787
1845
  "Content-Type": "application/json",
@@ -1792,18 +1850,28 @@ window.__ModuleLoader__.load({
1792
1850
  if (!res.ok || !json.ok) throw new Error(json.error || `HTTP ${res.status}`);
1793
1851
  return json.value;
1794
1852
  }
1795
- function parsePositiveCapacity$3(value) {
1853
+ function parsePositiveCapacity$4(value) {
1796
1854
  const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
1797
1855
  if (matched === null) return null;
1798
1856
  const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
1799
1857
  const parsed = Number(matched[1]) * multiplier;
1800
1858
  return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
1801
1859
  }
1802
- function formatCapacity$3(value) {
1860
+ function formatCapacity$4(value) {
1803
1861
  if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
1804
1862
  if (value % 1e3 === 0) return `${value / 1e3}K`;
1805
1863
  return String(value);
1806
1864
  }
1865
+ /**
1866
+ * Seed one draft per model from a status payload. Also run after a model
1867
+ * toggle: a model that was just enabled has no draft yet, and the context
1868
+ * window section only renders enabled models.
1869
+ */
1870
+ function contextDraftsFor$4(status) {
1871
+ const drafts = {};
1872
+ for (const model of status.models) drafts[model.id] = formatCapacity$4(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
1873
+ return drafts;
1874
+ }
1807
1875
  function formatResetTime(resetTime) {
1808
1876
  if (!resetTime) return "";
1809
1877
  const diff = new Date(resetTime).getTime() - Date.now();
@@ -1815,7 +1883,7 @@ window.__ModuleLoader__.load({
1815
1883
  if (hours > 0) return `${hours}h ${mins % 60}m`;
1816
1884
  return `${mins}m`;
1817
1885
  }
1818
- function formatDate$2(ms) {
1886
+ function formatDate$3(ms) {
1819
1887
  if (!ms || ms <= 0) return "—";
1820
1888
  try {
1821
1889
  return new Intl.DateTimeFormat(void 0, {
@@ -1835,7 +1903,7 @@ window.__ModuleLoader__.load({
1835
1903
  const [loginProgress, setLoginProgress] = (0, react.useState)(null);
1836
1904
  const [contextDrafts, setContextDrafts] = (0, react.useState)({});
1837
1905
  const [savingModel, setSavingModel] = (0, react.useState)(null);
1838
- const t = zh$4;
1906
+ const t = zh$5;
1839
1907
  const notifyChange = (0, react.useCallback)(() => {
1840
1908
  onModelChange?.();
1841
1909
  loadModelDirectory?.();
@@ -1846,14 +1914,9 @@ window.__ModuleLoader__.load({
1846
1914
  setValidationUrl(null);
1847
1915
  }
1848
1916
  try {
1849
- const data = await fetchApi$7("/status");
1917
+ const data = await fetchApi$9("/status");
1850
1918
  setStatus(data);
1851
- const drafts = {};
1852
- for (const m of data.models) {
1853
- const val = data.contextWindowOverrides[m.id] || m.defaultContextWindow;
1854
- drafts[m.id] = formatCapacity$3(val);
1855
- }
1856
- setContextDrafts(drafts);
1919
+ setContextDrafts(contextDraftsFor$4(data));
1857
1920
  } catch (err) {
1858
1921
  if (!quiet) setError(err instanceof Error ? err.message : String(err));
1859
1922
  } finally {
@@ -1878,11 +1941,11 @@ window.__ModuleLoader__.load({
1878
1941
  setError(null);
1879
1942
  setValidationUrl(null);
1880
1943
  setLoginProgress(null);
1881
- const flow = await fetchApi$7("/login", { method: "POST" });
1944
+ const flow = await fetchApi$9("/login", { method: "POST" });
1882
1945
  if (flow.authUrl) window.open(flow.authUrl, "_blank");
1883
1946
  const pollTimer = setInterval(async () => {
1884
1947
  try {
1885
- const pollStatus = await fetchApi$7("/login/status");
1948
+ const pollStatus = await fetchApi$9("/login/status");
1886
1949
  if (pollStatus.progress) setLoginProgress(pollStatus.progress);
1887
1950
  if (pollStatus.status === "complete") {
1888
1951
  clearInterval(pollTimer);
@@ -1914,7 +1977,7 @@ window.__ModuleLoader__.load({
1914
1977
  try {
1915
1978
  setBusy("quota");
1916
1979
  setError(null);
1917
- const updated = await fetchApi$7("/quota", { method: "POST" });
1980
+ const updated = await fetchApi$9("/quota", { method: "POST" });
1918
1981
  setStatus(updated);
1919
1982
  } catch (err) {
1920
1983
  setError(err instanceof Error ? err.message : String(err));
@@ -1926,7 +1989,7 @@ window.__ModuleLoader__.load({
1926
1989
  try {
1927
1990
  setBusy(`primary-${accountId}`);
1928
1991
  setError(null);
1929
- const updated = await fetchApi$7("/accounts", {
1992
+ const updated = await fetchApi$9("/accounts", {
1930
1993
  method: "POST",
1931
1994
  body: JSON.stringify({
1932
1995
  action: "set-primary",
@@ -1945,7 +2008,7 @@ window.__ModuleLoader__.load({
1945
2008
  try {
1946
2009
  setBusy(`delete-${accountId}`);
1947
2010
  setError(null);
1948
- const updated = await fetchApi$7("/accounts", {
2011
+ const updated = await fetchApi$9("/accounts", {
1949
2012
  method: "POST",
1950
2013
  body: JSON.stringify({
1951
2014
  action: "delete",
@@ -1964,7 +2027,7 @@ window.__ModuleLoader__.load({
1964
2027
  try {
1965
2028
  setBusy(`cooldown-${accountId}`);
1966
2029
  setError(null);
1967
- const updated = await fetchApi$7("/accounts", {
2030
+ const updated = await fetchApi$9("/accounts", {
1968
2031
  method: "POST",
1969
2032
  body: JSON.stringify({
1970
2033
  action: "clear-cooldown",
@@ -1982,7 +2045,7 @@ window.__ModuleLoader__.load({
1982
2045
  try {
1983
2046
  setBusy("strategy");
1984
2047
  setError(null);
1985
- const updated = await fetchApi$7("/accounts", {
2048
+ const updated = await fetchApi$9("/accounts", {
1986
2049
  method: "POST",
1987
2050
  body: JSON.stringify({
1988
2051
  action: "strategy",
@@ -2002,7 +2065,7 @@ window.__ModuleLoader__.load({
2002
2065
  enabled
2003
2066
  } : prev);
2004
2067
  try {
2005
- const updated = await fetchApi$7("/settings", {
2068
+ const updated = await fetchApi$9("/settings", {
2006
2069
  method: "POST",
2007
2070
  body: JSON.stringify({ enabled })
2008
2071
  });
@@ -2018,11 +2081,12 @@ window.__ModuleLoader__.load({
2018
2081
  const currentEnabled = status.models.filter((m) => m.enabled).map((m) => m.id);
2019
2082
  const nextEnabled = checked ? [.../* @__PURE__ */ new Set([...currentEnabled, modelId])] : currentEnabled.filter((id) => id !== modelId);
2020
2083
  try {
2021
- const updated = await fetchApi$7("/models", {
2084
+ const updated = await fetchApi$9("/models", {
2022
2085
  method: "POST",
2023
2086
  body: JSON.stringify({ enabledModelIds: nextEnabled })
2024
2087
  });
2025
2088
  setStatus(updated);
2089
+ setContextDrafts(contextDraftsFor$4(updated));
2026
2090
  notifyChange();
2027
2091
  } catch (err) {
2028
2092
  setError(err instanceof Error ? err.message : String(err));
@@ -2032,11 +2096,12 @@ window.__ModuleLoader__.load({
2032
2096
  if (!status) return;
2033
2097
  const nextEnabled = selectAll ? status.models.map((m) => m.id) : [];
2034
2098
  try {
2035
- const updated = await fetchApi$7("/models", {
2099
+ const updated = await fetchApi$9("/models", {
2036
2100
  method: "POST",
2037
2101
  body: JSON.stringify({ enabledModelIds: nextEnabled })
2038
2102
  });
2039
2103
  setStatus(updated);
2104
+ setContextDrafts(contextDraftsFor$4(updated));
2040
2105
  notifyChange();
2041
2106
  } catch (err) {
2042
2107
  setError(err instanceof Error ? err.message : String(err));
@@ -2044,7 +2109,7 @@ window.__ModuleLoader__.load({
2044
2109
  };
2045
2110
  const handleUpdateEffort = async (effort) => {
2046
2111
  try {
2047
- const updated = await fetchApi$7("/settings", {
2112
+ const updated = await fetchApi$9("/settings", {
2048
2113
  method: "POST",
2049
2114
  body: JSON.stringify({ defaultReasoningEffort: effort })
2050
2115
  });
@@ -2056,7 +2121,7 @@ window.__ModuleLoader__.load({
2056
2121
  };
2057
2122
  const handleSaveContextWindow = async (modelId) => {
2058
2123
  const raw = contextDrafts[modelId] || "";
2059
- const parsed = parsePositiveCapacity$3(raw);
2124
+ const parsed = parsePositiveCapacity$4(raw);
2060
2125
  if (parsed === null) {
2061
2126
  setError(`无效的上下文容量值: ${raw}`);
2062
2127
  return;
@@ -2064,14 +2129,14 @@ window.__ModuleLoader__.load({
2064
2129
  try {
2065
2130
  setSavingModel(modelId);
2066
2131
  setError(null);
2067
- const updated = await fetchApi$7("/settings", {
2132
+ const updated = await fetchApi$9("/settings", {
2068
2133
  method: "POST",
2069
2134
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
2070
2135
  });
2071
2136
  setStatus(updated);
2072
2137
  setContextDrafts((prev) => ({
2073
2138
  ...prev,
2074
- [modelId]: formatCapacity$3(parsed)
2139
+ [modelId]: formatCapacity$4(parsed)
2075
2140
  }));
2076
2141
  notifyChange();
2077
2142
  } catch (err) {
@@ -2080,6 +2145,53 @@ window.__ModuleLoader__.load({
2080
2145
  setSavingModel(null);
2081
2146
  }
2082
2147
  };
2148
+ /** Clear one override; the row falls back to the catalog length. */
2149
+ const handleResetContextWindow = async (modelId) => {
2150
+ try {
2151
+ setSavingModel(modelId);
2152
+ setError(null);
2153
+ const updated = await fetchApi$9("/settings", {
2154
+ method: "POST",
2155
+ body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
2156
+ });
2157
+ setStatus(updated);
2158
+ setContextDrafts((prev) => {
2159
+ const model = updated.models.find((candidate) => candidate.id === modelId);
2160
+ return model === void 0 ? prev : {
2161
+ ...prev,
2162
+ [modelId]: formatCapacity$4(model.defaultContextWindow)
2163
+ };
2164
+ });
2165
+ notifyChange();
2166
+ } catch (err) {
2167
+ setError(err instanceof Error ? err.message : String(err));
2168
+ } finally {
2169
+ setSavingModel(null);
2170
+ }
2171
+ };
2172
+ /** Clear every stored override, including models the picker no longer shows. */
2173
+ const handleResetAllContextWindows = async () => {
2174
+ const models = Object.keys(status?.contextWindowOverrides ?? {});
2175
+ if (models.length === 0) return;
2176
+ if (typeof window !== "undefined" && !window.confirm(t.contextWindowResetAllConfirm)) return;
2177
+ try {
2178
+ setBusy("context");
2179
+ setError(null);
2180
+ const updated = await fetchApi$9("/settings", {
2181
+ method: "POST",
2182
+ body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
2183
+ });
2184
+ setStatus(updated);
2185
+ setContextDrafts(contextDraftsFor$4(updated));
2186
+ notifyChange();
2187
+ } catch (err) {
2188
+ setError(err instanceof Error ? err.message : String(err));
2189
+ } finally {
2190
+ setBusy(null);
2191
+ }
2192
+ };
2193
+ const contextModels = status?.models.filter((model) => model.enabled) ?? [];
2194
+ const overrideCount = Object.keys(status?.contextWindowOverrides ?? {}).length;
2083
2195
  if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2084
2196
  className: "dsha-page",
2085
2197
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -2119,12 +2231,12 @@ window.__ModuleLoader__.load({
2119
2231
  account.expiresAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2120
2232
  t.expires,
2121
2233
  ": ",
2122
- formatDate$2(account.expiresAt)
2234
+ formatDate$3(account.expiresAt)
2123
2235
  ] }),
2124
2236
  account.lastUsedAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2125
2237
  t.lastUsed,
2126
2238
  ": ",
2127
- formatDate$2(account.lastUsedAt)
2239
+ formatDate$3(account.lastUsedAt)
2128
2240
  ] })
2129
2241
  ] })
2130
2242
  }),
@@ -2256,35 +2368,58 @@ window.__ModuleLoader__.load({
2256
2368
  className: "dsha-muted",
2257
2369
  children: t.contextWindowHint
2258
2370
  }),
2259
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2371
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2260
2372
  className: "dsha-context-settings",
2261
- children: status?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2262
- className: "dsha-context-row",
2263
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2264
- className: "dsha-capacity-control",
2265
- children: [
2266
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2267
- type: "text",
2268
- value: contextDrafts[model.id] ?? "",
2269
- onChange: (e) => setContextDrafts({
2270
- ...contextDrafts,
2271
- [model.id]: e.target.value
2373
+ children: [
2374
+ contextModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2375
+ className: "dsha-muted",
2376
+ children: t.contextWindowNoneEnabled
2377
+ }),
2378
+ contextModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2379
+ className: "dsha-context-row",
2380
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2381
+ className: "dsha-capacity-control",
2382
+ children: [
2383
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2384
+ type: "text",
2385
+ value: contextDrafts[model.id] ?? "",
2386
+ onChange: (e) => setContextDrafts({
2387
+ ...contextDrafts,
2388
+ [model.id]: e.target.value
2389
+ }),
2390
+ onKeyDown: (e) => {
2391
+ if (e.key === "Enter") handleSaveContextWindow(model.id);
2392
+ }
2272
2393
  }),
2273
- onKeyDown: (e) => {
2274
- if (e.key === "Enter") handleSaveContextWindow(model.id);
2275
- }
2276
- }),
2277
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
2278
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2279
- type: "button",
2280
- className: "dsha-context-save",
2281
- disabled: savingModel === model.id,
2282
- onClick: () => void handleSaveContextWindow(model.id),
2283
- children: savingModel === model.id ? t.saving : t.save
2284
- })
2285
- ]
2286
- })]
2287
- }, model.id))
2394
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
2395
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2396
+ type: "button",
2397
+ className: "dsha-context-save",
2398
+ disabled: savingModel === model.id,
2399
+ onClick: () => void handleSaveContextWindow(model.id),
2400
+ children: savingModel === model.id ? t.saving : t.save
2401
+ }),
2402
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2403
+ type: "button",
2404
+ className: "dsha-context-save dsha-context-reset",
2405
+ "aria-label": `${model.name} ${t.contextWindowReset}`,
2406
+ disabled: savingModel === model.id || status?.contextWindowOverrides[model.id] === void 0,
2407
+ onClick: () => void handleResetContextWindow(model.id),
2408
+ children: t.contextWindowReset
2409
+ })
2410
+ ]
2411
+ })]
2412
+ }, model.id)),
2413
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2414
+ className: "dsha-actions",
2415
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2416
+ className: "dsha-btn",
2417
+ disabled: busy !== null || overrideCount === 0,
2418
+ onClick: () => void handleResetAllContextWindows(),
2419
+ children: t.contextWindowResetAll
2420
+ })
2421
+ })
2422
+ ]
2288
2423
  })
2289
2424
  ]
2290
2425
  }),
@@ -2380,7 +2515,7 @@ window.__ModuleLoader__.load({
2380
2515
  //#endregion
2381
2516
  //#region src/client/command-code/locales.ts
2382
2517
  const NS_COMMAND_CODE = "dsh-command-code";
2383
- const zh$3 = {
2518
+ const zh$4 = {
2384
2519
  ...accountPoolZh,
2385
2520
  title: "Command Code",
2386
2521
  pageDesc: "登录 Command Code,管理可用模型、上下文窗口与额度。",
@@ -2433,6 +2568,10 @@ window.__ModuleLoader__.load({
2433
2568
  defaultEffortAuto: "使用 Provider 默认值",
2434
2569
  contextWindowSection: "模型上下文窗口",
2435
2570
  contextWindowHint: "默认取 Command Code 模型目录的 context length;可覆盖为自定义容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
2571
+ contextWindowReset: "恢复默认",
2572
+ contextWindowResetAll: "全部恢复默认",
2573
+ contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
2574
+ contextWindowNoneEnabled: "还没有勾选任何模型。在上方勾选后,这里会出现该模型的上下文窗口设置。",
2436
2575
  save: "保存",
2437
2576
  saved: "已保存",
2438
2577
  saving: "保存中...",
@@ -2448,7 +2587,7 @@ window.__ModuleLoader__.load({
2448
2587
  loginFailed: "登录失败",
2449
2588
  tokens: "tokens"
2450
2589
  };
2451
- const en$3 = {
2590
+ const en$4 = {
2452
2591
  ...accountPoolEn,
2453
2592
  title: "Command Code",
2454
2593
  pageDesc: "Sign in to Command Code and manage models, context windows, and quota.",
@@ -2501,6 +2640,10 @@ window.__ModuleLoader__.load({
2501
2640
  defaultEffortAuto: "Use provider default",
2502
2641
  contextWindowSection: "Model context window",
2503
2642
  contextWindowHint: "Defaults to the context length in the Command Code catalog; override it with the capacity DSH should use for compaction and overflow decisions (e.g., 1M, 512K, 200K).",
2643
+ contextWindowReset: "Restore default",
2644
+ contextWindowResetAll: "Restore all defaults",
2645
+ contextWindowResetAllConfirm: "Restore every changed model context window to its default?",
2646
+ contextWindowNoneEnabled: "No model is checked yet. Check one above and its context window setting appears here.",
2504
2647
  save: "Save",
2505
2648
  saved: "Saved",
2506
2649
  saving: "Saving...",
@@ -2516,11 +2659,11 @@ window.__ModuleLoader__.load({
2516
2659
  loginFailed: "Sign-in failed",
2517
2660
  tokens: "tokens"
2518
2661
  };
2519
- const dictionaries$3 = {
2520
- zh: zh$3,
2521
- "zh-CN": zh$3,
2522
- en: en$3,
2523
- "en-US": en$3
2662
+ const dictionaries$4 = {
2663
+ zh: zh$4,
2664
+ "zh-CN": zh$4,
2665
+ en: en$4,
2666
+ "en-US": en$4
2524
2667
  };
2525
2668
  //#endregion
2526
2669
  //#region src/client/command-code/CommandCodeSection.tsx
@@ -2528,7 +2671,7 @@ window.__ModuleLoader__.load({
2528
2671
  * Display label per reasoning level. The locale dictionary only accepts flat
2529
2672
  * string values, so this nested table lives with the control that renders it.
2530
2673
  */
2531
- const EFFORT_LABELS$1 = {
2674
+ const EFFORT_LABELS$2 = {
2532
2675
  minimal: "Minimal",
2533
2676
  low: "Low",
2534
2677
  medium: "Medium",
@@ -2536,9 +2679,9 @@ window.__ModuleLoader__.load({
2536
2679
  xhigh: "X-High",
2537
2680
  max: "Max"
2538
2681
  };
2539
- const API$6 = "/command-code/api";
2540
- async function fetchApi$6(path, options) {
2541
- const res = await fetch(`${API$6}${path}`, {
2682
+ const API$8 = "/command-code/api";
2683
+ async function fetchApi$8(path, options) {
2684
+ const res = await fetch(`${API$8}${path}`, {
2542
2685
  ...options,
2543
2686
  headers: {
2544
2687
  "Content-Type": "application/json",
@@ -2550,19 +2693,29 @@ window.__ModuleLoader__.load({
2550
2693
  return json.value;
2551
2694
  }
2552
2695
  /** Parse "1M", "512K", "200000" into a positive integer token count. */
2553
- function parsePositiveCapacity$2(value) {
2696
+ function parsePositiveCapacity$3(value) {
2554
2697
  const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
2555
2698
  if (matched === null) return null;
2556
2699
  const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
2557
2700
  const parsed = Number(matched[1]) * multiplier;
2558
2701
  return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
2559
2702
  }
2560
- function formatCapacity$2(value) {
2703
+ function formatCapacity$3(value) {
2561
2704
  if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
2562
2705
  if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
2563
2706
  return String(value);
2564
2707
  }
2565
- function formatReset$2(resetsAt) {
2708
+ /**
2709
+ * Seed one draft per model from a status payload. Also run after a model
2710
+ * toggle: a model that was just enabled has no draft yet, and the context
2711
+ * window section only renders enabled models.
2712
+ */
2713
+ function contextDraftsFor$3(status) {
2714
+ const drafts = {};
2715
+ for (const model of status.models) drafts[model.id] = formatCapacity$3(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
2716
+ return drafts;
2717
+ }
2718
+ function formatReset$3(resetsAt) {
2566
2719
  if (resetsAt === void 0 || resetsAt === null || resetsAt <= 0) return "";
2567
2720
  const diff = resetsAt - Date.now();
2568
2721
  if (diff <= 0) return "now";
@@ -2582,7 +2735,7 @@ window.__ModuleLoader__.load({
2582
2735
  const [contextDrafts, setContextDrafts] = (0, react.useState)({});
2583
2736
  const [savingModel, setSavingModel] = (0, react.useState)(null);
2584
2737
  const [apiKey, setApiKey] = (0, react.useState)("");
2585
- const t = zh$3;
2738
+ const t = zh$4;
2586
2739
  const notifyChange = (0, react.useCallback)(() => {
2587
2740
  onModelChange?.();
2588
2741
  loadModelDirectory?.();
@@ -2590,11 +2743,9 @@ window.__ModuleLoader__.load({
2590
2743
  const loadStatus = (0, react.useCallback)(async (quiet = false) => {
2591
2744
  if (!quiet) setError(null);
2592
2745
  try {
2593
- const data = await fetchApi$6("/status");
2746
+ const data = await fetchApi$8("/status");
2594
2747
  setStatus(data);
2595
- const drafts = {};
2596
- for (const model of data.models) drafts[model.id] = formatCapacity$2(data.contextWindowOverrides[model.id] || model.defaultContextWindow);
2597
- setContextDrafts(drafts);
2748
+ setContextDrafts(contextDraftsFor$3(data));
2598
2749
  } catch (err) {
2599
2750
  if (!quiet) setError(err instanceof Error ? err.message : String(err));
2600
2751
  } finally {
@@ -2618,12 +2769,12 @@ window.__ModuleLoader__.load({
2618
2769
  setBusy("login");
2619
2770
  setError(null);
2620
2771
  setLoginProgress(null);
2621
- const flow = await fetchApi$6("/login", { method: "POST" });
2772
+ const flow = await fetchApi$8("/login", { method: "POST" });
2622
2773
  if (flow.authUrl) window.open(flow.authUrl, "_blank");
2623
2774
  const pollTimer = window.setInterval(() => {
2624
2775
  (async () => {
2625
2776
  try {
2626
- const poll = await fetchApi$6("/login/status");
2777
+ const poll = await fetchApi$8("/login/status");
2627
2778
  if (poll.progress) setLoginProgress(poll.progress);
2628
2779
  if (poll.status === "complete") {
2629
2780
  window.clearInterval(pollTimer);
@@ -2655,7 +2806,7 @@ window.__ModuleLoader__.load({
2655
2806
  try {
2656
2807
  setBusy("apikey");
2657
2808
  setError(null);
2658
- const updated = await fetchApi$6("/login/apikey", {
2809
+ const updated = await fetchApi$8("/login/apikey", {
2659
2810
  method: "POST",
2660
2811
  body: JSON.stringify({ apiKey })
2661
2812
  });
@@ -2673,7 +2824,7 @@ window.__ModuleLoader__.load({
2673
2824
  try {
2674
2825
  setBusy(`${action}-${accountId}`);
2675
2826
  setError(null);
2676
- const updated = await fetchApi$6("/accounts", {
2827
+ const updated = await fetchApi$8("/accounts", {
2677
2828
  method: "POST",
2678
2829
  body: JSON.stringify({
2679
2830
  action,
@@ -2692,7 +2843,7 @@ window.__ModuleLoader__.load({
2692
2843
  try {
2693
2844
  setBusy("strategy");
2694
2845
  setError(null);
2695
- const updated = await fetchApi$6("/accounts", {
2846
+ const updated = await fetchApi$8("/accounts", {
2696
2847
  method: "POST",
2697
2848
  body: JSON.stringify({
2698
2849
  action: "strategy",
@@ -2715,7 +2866,7 @@ window.__ModuleLoader__.load({
2715
2866
  const handleRelogin = (accountId) => {
2716
2867
  (async () => {
2717
2868
  try {
2718
- const updated = await fetchApi$6("/accounts", {
2869
+ const updated = await fetchApi$8("/accounts", {
2719
2870
  method: "POST",
2720
2871
  body: JSON.stringify({
2721
2872
  action: "relogin",
@@ -2734,7 +2885,7 @@ window.__ModuleLoader__.load({
2734
2885
  try {
2735
2886
  setBusy("quota");
2736
2887
  setError(null);
2737
- const updated = await fetchApi$6("/quota", { method: "POST" });
2888
+ const updated = await fetchApi$8("/quota", { method: "POST" });
2738
2889
  setStatus(updated);
2739
2890
  } catch (err) {
2740
2891
  setError(err instanceof Error ? err.message : String(err));
@@ -2746,11 +2897,9 @@ window.__ModuleLoader__.load({
2746
2897
  try {
2747
2898
  setBusy("catalog");
2748
2899
  setError(null);
2749
- const updated = await fetchApi$6("/catalog/refresh", { method: "POST" });
2900
+ const updated = await fetchApi$8("/catalog/refresh", { method: "POST" });
2750
2901
  setStatus(updated);
2751
- const drafts = {};
2752
- for (const model of updated.models) drafts[model.id] = formatCapacity$2(updated.contextWindowOverrides[model.id] || model.defaultContextWindow);
2753
- setContextDrafts(drafts);
2902
+ setContextDrafts(contextDraftsFor$3(updated));
2754
2903
  notifyChange();
2755
2904
  } catch (err) {
2756
2905
  setError(err instanceof Error ? err.message : String(err));
@@ -2762,7 +2911,7 @@ window.__ModuleLoader__.load({
2762
2911
  try {
2763
2912
  setBusy("connection");
2764
2913
  setError(null);
2765
- await fetchApi$6("/connection/test", { method: "POST" });
2914
+ await fetchApi$8("/connection/test", { method: "POST" });
2766
2915
  await loadStatus(true);
2767
2916
  } catch (err) {
2768
2917
  setError(err instanceof Error ? err.message : String(err));
@@ -2772,11 +2921,12 @@ window.__ModuleLoader__.load({
2772
2921
  };
2773
2922
  const applyEnabled = async (enabledModelIds) => {
2774
2923
  try {
2775
- const updated = await fetchApi$6("/models", {
2924
+ const updated = await fetchApi$8("/models", {
2776
2925
  method: "POST",
2777
2926
  body: JSON.stringify({ enabledModelIds })
2778
2927
  });
2779
2928
  setStatus(updated);
2929
+ setContextDrafts(contextDraftsFor$3(updated));
2780
2930
  notifyChange();
2781
2931
  } catch (err) {
2782
2932
  setError(err instanceof Error ? err.message : String(err));
@@ -2788,7 +2938,7 @@ window.__ModuleLoader__.load({
2788
2938
  enabled
2789
2939
  } : prev);
2790
2940
  try {
2791
- const updated = await fetchApi$6("/settings", {
2941
+ const updated = await fetchApi$8("/settings", {
2792
2942
  method: "POST",
2793
2943
  body: JSON.stringify({ enabled })
2794
2944
  });
@@ -2811,7 +2961,7 @@ window.__ModuleLoader__.load({
2811
2961
  };
2812
2962
  const handleUpdateEffort = async (effort) => {
2813
2963
  try {
2814
- const updated = await fetchApi$6("/settings", {
2964
+ const updated = await fetchApi$8("/settings", {
2815
2965
  method: "POST",
2816
2966
  body: JSON.stringify({ defaultReasoningEffort: effort })
2817
2967
  });
@@ -2823,7 +2973,7 @@ window.__ModuleLoader__.load({
2823
2973
  };
2824
2974
  const handleSaveContextWindow = async (modelId) => {
2825
2975
  const raw = contextDrafts[modelId] || "";
2826
- const parsed = parsePositiveCapacity$2(raw);
2976
+ const parsed = parsePositiveCapacity$3(raw);
2827
2977
  if (parsed === null) {
2828
2978
  setError(`Invalid context capacity: ${raw}`);
2829
2979
  return;
@@ -2831,14 +2981,14 @@ window.__ModuleLoader__.load({
2831
2981
  try {
2832
2982
  setSavingModel(modelId);
2833
2983
  setError(null);
2834
- const updated = await fetchApi$6("/settings", {
2984
+ const updated = await fetchApi$8("/settings", {
2835
2985
  method: "POST",
2836
2986
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
2837
2987
  });
2838
2988
  setStatus(updated);
2839
2989
  setContextDrafts((prev) => ({
2840
2990
  ...prev,
2841
- [modelId]: formatCapacity$2(parsed)
2991
+ [modelId]: formatCapacity$3(parsed)
2842
2992
  }));
2843
2993
  notifyChange();
2844
2994
  } catch (err) {
@@ -2847,6 +2997,53 @@ window.__ModuleLoader__.load({
2847
2997
  setSavingModel(null);
2848
2998
  }
2849
2999
  };
3000
+ /** Clear one override; the row falls back to the catalog length. */
3001
+ const handleResetContextWindow = async (modelId) => {
3002
+ try {
3003
+ setSavingModel(modelId);
3004
+ setError(null);
3005
+ const updated = await fetchApi$8("/settings", {
3006
+ method: "POST",
3007
+ body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
3008
+ });
3009
+ setStatus(updated);
3010
+ setContextDrafts((prev) => {
3011
+ const model = updated.models.find((candidate) => candidate.id === modelId);
3012
+ return model === void 0 ? prev : {
3013
+ ...prev,
3014
+ [modelId]: formatCapacity$3(model.defaultContextWindow)
3015
+ };
3016
+ });
3017
+ notifyChange();
3018
+ } catch (err) {
3019
+ setError(err instanceof Error ? err.message : String(err));
3020
+ } finally {
3021
+ setSavingModel(null);
3022
+ }
3023
+ };
3024
+ /** Clear every stored override, including models the picker no longer shows. */
3025
+ const handleResetAllContextWindows = async () => {
3026
+ const models = Object.keys(status?.contextWindowOverrides ?? {});
3027
+ if (models.length === 0) return;
3028
+ if (typeof window !== "undefined" && !window.confirm(t.contextWindowResetAllConfirm)) return;
3029
+ try {
3030
+ setBusy("context");
3031
+ setError(null);
3032
+ const updated = await fetchApi$8("/settings", {
3033
+ method: "POST",
3034
+ body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
3035
+ });
3036
+ setStatus(updated);
3037
+ setContextDrafts(contextDraftsFor$3(updated));
3038
+ notifyChange();
3039
+ } catch (err) {
3040
+ setError(err instanceof Error ? err.message : String(err));
3041
+ } finally {
3042
+ setBusy(null);
3043
+ }
3044
+ };
3045
+ const contextModels = status?.models.filter((model) => model.enabled) ?? [];
3046
+ const overrideCount = Object.keys(status?.contextWindowOverrides ?? {}).length;
2850
3047
  if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2851
3048
  className: "dsha-page",
2852
3049
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -3034,7 +3231,7 @@ window.__ModuleLoader__.load({
3034
3231
  children: t.defaultEffortAuto
3035
3232
  }), COMMAND_CODE_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
3036
3233
  value: effort,
3037
- children: EFFORT_LABELS$1[effort]
3234
+ children: EFFORT_LABELS$2[effort]
3038
3235
  }, effort))]
3039
3236
  })]
3040
3237
  })]
@@ -3050,39 +3247,62 @@ window.__ModuleLoader__.load({
3050
3247
  className: "dsha-muted",
3051
3248
  children: t.contextWindowHint
3052
3249
  }),
3053
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3250
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3054
3251
  className: "dsha-context-settings",
3055
- children: status?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3056
- className: "dsha-context-row",
3057
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3058
- title: model.id,
3059
- children: model.name
3060
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3061
- className: "dsha-capacity-control",
3062
- children: [
3063
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3064
- type: "text",
3065
- "aria-label": `${model.name} context window`,
3066
- value: contextDrafts[model.id] ?? "",
3067
- onChange: (event) => setContextDrafts({
3068
- ...contextDrafts,
3069
- [model.id]: event.currentTarget.value
3252
+ children: [
3253
+ contextModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3254
+ className: "dsha-muted",
3255
+ children: t.contextWindowNoneEnabled
3256
+ }),
3257
+ contextModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3258
+ className: "dsha-context-row",
3259
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3260
+ title: model.id,
3261
+ children: model.name
3262
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3263
+ className: "dsha-capacity-control",
3264
+ children: [
3265
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3266
+ type: "text",
3267
+ "aria-label": `${model.name} context window`,
3268
+ value: contextDrafts[model.id] ?? "",
3269
+ onChange: (event) => setContextDrafts({
3270
+ ...contextDrafts,
3271
+ [model.id]: event.currentTarget.value
3272
+ }),
3273
+ onKeyDown: (event) => {
3274
+ if (event.key === "Enter") handleSaveContextWindow(model.id);
3275
+ }
3070
3276
  }),
3071
- onKeyDown: (event) => {
3072
- if (event.key === "Enter") handleSaveContextWindow(model.id);
3073
- }
3074
- }),
3075
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
3076
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3077
- type: "button",
3078
- className: "dsha-context-save",
3079
- disabled: savingModel === model.id,
3080
- onClick: () => void handleSaveContextWindow(model.id),
3081
- children: savingModel === model.id ? t.saving : t.save
3082
- })
3083
- ]
3084
- })]
3085
- }, model.id))
3277
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
3278
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3279
+ type: "button",
3280
+ className: "dsha-context-save",
3281
+ disabled: savingModel === model.id,
3282
+ onClick: () => void handleSaveContextWindow(model.id),
3283
+ children: savingModel === model.id ? t.saving : t.save
3284
+ }),
3285
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3286
+ type: "button",
3287
+ className: "dsha-context-save dsha-context-reset",
3288
+ "aria-label": `${model.name} ${t.contextWindowReset}`,
3289
+ disabled: savingModel === model.id || status?.contextWindowOverrides[model.id] === void 0,
3290
+ onClick: () => void handleResetContextWindow(model.id),
3291
+ children: t.contextWindowReset
3292
+ })
3293
+ ]
3294
+ })]
3295
+ }, model.id)),
3296
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3297
+ className: "dsha-actions",
3298
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3299
+ className: "dsha-btn",
3300
+ disabled: busy !== null || overrideCount === 0,
3301
+ onClick: () => void handleResetAllContextWindows(),
3302
+ children: t.contextWindowResetAll
3303
+ })
3304
+ })
3305
+ ]
3086
3306
  })
3087
3307
  ]
3088
3308
  }),
@@ -3128,7 +3348,7 @@ window.__ModuleLoader__.load({
3128
3348
  }),
3129
3349
  window.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3130
3350
  className: "dsha-meter-meta",
3131
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$2(window.resetsAt)] })
3351
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$3(window.resetsAt)] })
3132
3352
  })
3133
3353
  ]
3134
3354
  }, window.id)),
@@ -3153,7 +3373,7 @@ window.__ModuleLoader__.load({
3153
3373
  meter.used ?? "—",
3154
3374
  " / ",
3155
3375
  meter.limit ?? "—"
3156
- ] }), meter.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$2(meter.resetsAt)] })]
3376
+ ] }), meter.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$3(meter.resetsAt)] })]
3157
3377
  }) : meter.description !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3158
3378
  className: "dsha-meter-meta",
3159
3379
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meter.description })
@@ -3192,7 +3412,7 @@ window.__ModuleLoader__.load({
3192
3412
  //#endregion
3193
3413
  //#region src/client/kimi-code/locales.ts
3194
3414
  const NS_KIMI_CODE = "dsh-kimi-code";
3195
- const zh$2 = {
3415
+ const zh$3 = {
3196
3416
  ...accountPoolZh,
3197
3417
  title: "Kimi Code",
3198
3418
  pageDesc: "登录 Kimi Code 订阅,管理模型、思考档位、上下文窗口与额度。",
@@ -3272,6 +3492,10 @@ window.__ModuleLoader__.load({
3272
3492
  contextWindowSection: "模型上下文窗口",
3273
3493
  contextWindowHint: "默认取模型目录的上下文长度。k3 的 1M 上下文需要 Allegretto 及以上套餐,因此默认按 256K 计算;如已升级可在此覆盖为 1M。",
3274
3494
  contextWindowPlan: "完整上下文需要 {plan} 套餐",
3495
+ contextWindowReset: "恢复默认",
3496
+ contextWindowResetAll: "全部恢复默认",
3497
+ contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
3498
+ contextWindowNoneEnabled: "还没有勾选任何模型。在上方勾选后,这里会出现该模型的上下文窗口设置。",
3275
3499
  save: "保存",
3276
3500
  saved: "已保存",
3277
3501
  saving: "保存中...",
@@ -3312,7 +3536,7 @@ window.__ModuleLoader__.load({
3312
3536
  requests: "次请求",
3313
3537
  tokens: "tokens"
3314
3538
  };
3315
- const en$2 = {
3539
+ const en$3 = {
3316
3540
  ...accountPoolEn,
3317
3541
  title: "Kimi Code",
3318
3542
  pageDesc: "Sign in to the Kimi Code subscription and manage models, thinking level, context windows, and quota.",
@@ -3392,6 +3616,10 @@ window.__ModuleLoader__.load({
3392
3616
  contextWindowSection: "Model context window",
3393
3617
  contextWindowHint: "Defaults to the catalog context length. k3 reaches 1M only on Allegretto and above, so it defaults to 256K; raise the override here after upgrading.",
3394
3618
  contextWindowPlan: "Full context requires the {plan} plan",
3619
+ contextWindowReset: "Restore default",
3620
+ contextWindowResetAll: "Restore all defaults",
3621
+ contextWindowResetAllConfirm: "Restore every changed model context window to its default?",
3622
+ contextWindowNoneEnabled: "No model is checked yet. Check one above and its context window setting appears here.",
3395
3623
  save: "Save",
3396
3624
  saved: "Saved",
3397
3625
  saving: "Saving...",
@@ -3432,11 +3660,11 @@ window.__ModuleLoader__.load({
3432
3660
  requests: "requests",
3433
3661
  tokens: "tokens"
3434
3662
  };
3435
- const dictionaries$2 = {
3436
- zh: zh$2,
3437
- "zh-CN": zh$2,
3438
- en: en$2,
3439
- "en-US": en$2
3663
+ const dictionaries$3 = {
3664
+ zh: zh$3,
3665
+ "zh-CN": zh$3,
3666
+ en: en$3,
3667
+ "en-US": en$3
3440
3668
  };
3441
3669
  //#endregion
3442
3670
  //#region src/client/kimi-code/KimiModelCapabilities.tsx
@@ -3449,7 +3677,7 @@ window.__ModuleLoader__.load({
3449
3677
  * Capabilities are now short tags in their own columns, with the per-model
3450
3678
  * detail kept in a hover title.
3451
3679
  */
3452
- const t = zh$2;
3680
+ const t = zh$3;
3453
3681
  function KimiModelCapabilities({ models }) {
3454
3682
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3455
3683
  className: "dsha-cap-table",
@@ -3493,9 +3721,9 @@ window.__ModuleLoader__.load({
3493
3721
  }
3494
3722
  //#endregion
3495
3723
  //#region src/client/kimi-code/KimiCodeSection.tsx
3496
- const API$5 = "/kimi-code/api";
3497
- async function fetchApi$5(path, options) {
3498
- const res = await fetch(`${API$5}${path}`, {
3724
+ const API$7 = "/kimi-code/api";
3725
+ async function fetchApi$7(path, options) {
3726
+ const res = await fetch(`${API$7}${path}`, {
3499
3727
  ...options,
3500
3728
  headers: {
3501
3729
  "Content-Type": "application/json",
@@ -3507,19 +3735,29 @@ window.__ModuleLoader__.load({
3507
3735
  return json.value;
3508
3736
  }
3509
3737
  /** Parse "1M", "512K", "200000" into a positive integer token count. */
3510
- function parsePositiveCapacity$1(value) {
3738
+ function parsePositiveCapacity$2(value) {
3511
3739
  const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
3512
3740
  if (matched === null) return null;
3513
3741
  const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
3514
3742
  const parsed = Number(matched[1]) * multiplier;
3515
3743
  return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
3516
3744
  }
3517
- function formatCapacity$1(value) {
3745
+ function formatCapacity$2(value) {
3518
3746
  if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
3519
3747
  if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
3520
3748
  return String(value);
3521
3749
  }
3522
- function formatDate$1(ms) {
3750
+ /**
3751
+ * Seed one draft per model from a status payload. Also run after a model
3752
+ * toggle: a model that was just enabled has no draft yet, and the context
3753
+ * window section only renders enabled models.
3754
+ */
3755
+ function contextDraftsFor$2(status) {
3756
+ const drafts = {};
3757
+ for (const model of status.models) drafts[model.id] = formatCapacity$2(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
3758
+ return drafts;
3759
+ }
3760
+ function formatDate$2(ms) {
3523
3761
  if (ms === void 0 || ms === null || ms <= 0) return "—";
3524
3762
  try {
3525
3763
  return new Intl.DateTimeFormat(void 0, {
@@ -3530,7 +3768,7 @@ window.__ModuleLoader__.load({
3530
3768
  return "—";
3531
3769
  }
3532
3770
  }
3533
- function formatReset$1(resetsAt) {
3771
+ function formatReset$2(resetsAt) {
3534
3772
  if (resetsAt === void 0 || resetsAt === null || resetsAt <= 0) return "";
3535
3773
  const diff = resetsAt - Date.now();
3536
3774
  if (diff <= 0) return "now";
@@ -3555,10 +3793,10 @@ window.__ModuleLoader__.load({
3555
3793
  }
3556
3794
  }
3557
3795
  const EFFORT_LABEL = {
3558
- low: zh$2.effortLow,
3559
- high: zh$2.effortHigh,
3560
- max: zh$2.effortMax,
3561
- none: zh$2.effortNone
3796
+ low: zh$3.effortLow,
3797
+ high: zh$3.effortHigh,
3798
+ max: zh$3.effortMax,
3799
+ none: zh$3.effortNone
3562
3800
  };
3563
3801
  /** Human label for the last request's prefix-drift cause. */
3564
3802
  function driftLabel(cause, t) {
@@ -3582,7 +3820,7 @@ window.__ModuleLoader__.load({
3582
3820
  const [savingModel, setSavingModel] = (0, react.useState)(null);
3583
3821
  const [copied, setCopied] = (0, react.useState)(false);
3584
3822
  const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
3585
- const t = zh$2;
3823
+ const t = zh$3;
3586
3824
  const notifyChange = (0, react.useCallback)(() => {
3587
3825
  onModelChange?.();
3588
3826
  loadModelDirectory?.();
@@ -3590,11 +3828,9 @@ window.__ModuleLoader__.load({
3590
3828
  const loadStatus = (0, react.useCallback)(async (quiet = false) => {
3591
3829
  if (!quiet) setError(null);
3592
3830
  try {
3593
- const data = await fetchApi$5("/status");
3831
+ const data = await fetchApi$7("/status");
3594
3832
  setStatus(data);
3595
- const drafts = {};
3596
- for (const model of data.models) drafts[model.id] = formatCapacity$1(data.contextWindowOverrides[model.id] || model.defaultContextWindow);
3597
- setContextDrafts(drafts);
3833
+ setContextDrafts(contextDraftsFor$2(data));
3598
3834
  } catch (err) {
3599
3835
  if (!quiet) setError(err instanceof Error ? err.message : String(err));
3600
3836
  } finally {
@@ -3618,7 +3854,7 @@ window.__ModuleLoader__.load({
3618
3854
  const timer = window.setInterval(() => {
3619
3855
  (async () => {
3620
3856
  try {
3621
- const poll = await fetchApi$5("/login/status");
3857
+ const poll = await fetchApi$7("/login/status");
3622
3858
  setFlow(poll);
3623
3859
  if (poll.status === "complete") {
3624
3860
  await loadStatus();
@@ -3639,7 +3875,7 @@ window.__ModuleLoader__.load({
3639
3875
  setBusy("login");
3640
3876
  setError(null);
3641
3877
  setCopied(false);
3642
- const next = await fetchApi$5("/login", {
3878
+ const next = await fetchApi$7("/login", {
3643
3879
  method: "POST",
3644
3880
  body: JSON.stringify({})
3645
3881
  });
@@ -3652,7 +3888,7 @@ window.__ModuleLoader__.load({
3652
3888
  };
3653
3889
  const handleCancelLogin = async () => {
3654
3890
  try {
3655
- await fetchApi$5("/login/cancel", { method: "POST" });
3891
+ await fetchApi$7("/login/cancel", { method: "POST" });
3656
3892
  setFlow({ status: "idle" });
3657
3893
  } catch (err) {
3658
3894
  setError(err instanceof Error ? err.message : String(err));
@@ -3672,7 +3908,7 @@ window.__ModuleLoader__.load({
3672
3908
  try {
3673
3909
  setBusy(`${action}-${accountId}`);
3674
3910
  setError(null);
3675
- const updated = await fetchApi$5("/accounts", {
3911
+ const updated = await fetchApi$7("/accounts", {
3676
3912
  method: "POST",
3677
3913
  body: JSON.stringify({
3678
3914
  action,
@@ -3692,7 +3928,7 @@ window.__ModuleLoader__.load({
3692
3928
  try {
3693
3929
  setBusy("strategy");
3694
3930
  setError(null);
3695
- const updated = await fetchApi$5("/accounts", {
3931
+ const updated = await fetchApi$7("/accounts", {
3696
3932
  method: "POST",
3697
3933
  body: JSON.stringify({
3698
3934
  action: "strategy",
@@ -3715,7 +3951,7 @@ window.__ModuleLoader__.load({
3715
3951
  const handleRelogin = (accountId) => {
3716
3952
  (async () => {
3717
3953
  try {
3718
- const updated = await fetchApi$5("/accounts", {
3954
+ const updated = await fetchApi$7("/accounts", {
3719
3955
  method: "POST",
3720
3956
  body: JSON.stringify({
3721
3957
  action: "relogin",
@@ -3734,7 +3970,7 @@ window.__ModuleLoader__.load({
3734
3970
  try {
3735
3971
  setBusy("quota");
3736
3972
  setError(null);
3737
- const updated = await fetchApi$5("/quota", { method: "POST" });
3973
+ const updated = await fetchApi$7("/quota", { method: "POST" });
3738
3974
  setStatus(updated);
3739
3975
  } catch (err) {
3740
3976
  setError(err instanceof Error ? err.message : String(err));
@@ -3747,11 +3983,9 @@ window.__ModuleLoader__.load({
3747
3983
  try {
3748
3984
  setBusy("catalog");
3749
3985
  setError(null);
3750
- const updated = await fetchApi$5("/catalog/refresh", { method: "POST" });
3986
+ const updated = await fetchApi$7("/catalog/refresh", { method: "POST" });
3751
3987
  setStatus(updated);
3752
- const drafts = {};
3753
- for (const model of updated.models) drafts[model.id] = formatCapacity$1(updated.contextWindowOverrides[model.id] || model.defaultContextWindow);
3754
- setContextDrafts(drafts);
3988
+ setContextDrafts(contextDraftsFor$2(updated));
3755
3989
  notifyChange();
3756
3990
  } catch (err) {
3757
3991
  setError(err instanceof Error ? err.message : String(err));
@@ -3764,7 +3998,7 @@ window.__ModuleLoader__.load({
3764
3998
  setBusy("connection");
3765
3999
  setError(null);
3766
4000
  setConnectionNotice(null);
3767
- const result = await fetchApi$5("/connection/test", { method: "POST" });
4001
+ const result = await fetchApi$7("/connection/test", { method: "POST" });
3768
4002
  setConnectionNotice(result.connected ? `${t.testSuccess} · ${result.latencyMs} ms` : t.testFailed);
3769
4003
  await loadStatus(true);
3770
4004
  } catch (err) {
@@ -3775,11 +4009,12 @@ window.__ModuleLoader__.load({
3775
4009
  };
3776
4010
  const applyEnabled = async (enabledModelIds) => {
3777
4011
  try {
3778
- const updated = await fetchApi$5("/models", {
4012
+ const updated = await fetchApi$7("/models", {
3779
4013
  method: "POST",
3780
4014
  body: JSON.stringify({ enabledModelIds })
3781
4015
  });
3782
4016
  setStatus(updated);
4017
+ setContextDrafts(contextDraftsFor$2(updated));
3783
4018
  notifyChange();
3784
4019
  } catch (err) {
3785
4020
  setError(err instanceof Error ? err.message : String(err));
@@ -3791,7 +4026,7 @@ window.__ModuleLoader__.load({
3791
4026
  enabled
3792
4027
  } : prev);
3793
4028
  try {
3794
- const updated = await fetchApi$5("/settings", {
4029
+ const updated = await fetchApi$7("/settings", {
3795
4030
  method: "POST",
3796
4031
  body: JSON.stringify({ enabled })
3797
4032
  });
@@ -3814,7 +4049,7 @@ window.__ModuleLoader__.load({
3814
4049
  };
3815
4050
  const handleUpdateEffort = async (effort) => {
3816
4051
  try {
3817
- const updated = await fetchApi$5("/settings", {
4052
+ const updated = await fetchApi$7("/settings", {
3818
4053
  method: "POST",
3819
4054
  body: JSON.stringify({ defaultReasoningEffort: effort })
3820
4055
  });
@@ -3826,7 +4061,7 @@ window.__ModuleLoader__.load({
3826
4061
  };
3827
4062
  const handleSaveContextWindow = async (modelId) => {
3828
4063
  const raw = contextDrafts[modelId] || "";
3829
- const parsed = parsePositiveCapacity$1(raw);
4064
+ const parsed = parsePositiveCapacity$2(raw);
3830
4065
  if (parsed === null) {
3831
4066
  setError(`Invalid context capacity: ${raw}`);
3832
4067
  return;
@@ -3834,14 +4069,14 @@ window.__ModuleLoader__.load({
3834
4069
  try {
3835
4070
  setSavingModel(modelId);
3836
4071
  setError(null);
3837
- const updated = await fetchApi$5("/settings", {
4072
+ const updated = await fetchApi$7("/settings", {
3838
4073
  method: "POST",
3839
4074
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
3840
4075
  });
3841
4076
  setStatus(updated);
3842
4077
  setContextDrafts((prev) => ({
3843
4078
  ...prev,
3844
- [modelId]: formatCapacity$1(parsed)
4079
+ [modelId]: formatCapacity$2(parsed)
3845
4080
  }));
3846
4081
  notifyChange();
3847
4082
  } catch (err) {
@@ -3850,6 +4085,53 @@ window.__ModuleLoader__.load({
3850
4085
  setSavingModel(null);
3851
4086
  }
3852
4087
  };
4088
+ /** Clear one override; the row falls back to the catalog length. */
4089
+ const handleResetContextWindow = async (modelId) => {
4090
+ try {
4091
+ setSavingModel(modelId);
4092
+ setError(null);
4093
+ const updated = await fetchApi$7("/settings", {
4094
+ method: "POST",
4095
+ body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
4096
+ });
4097
+ setStatus(updated);
4098
+ setContextDrafts((prev) => {
4099
+ const model = updated.models.find((candidate) => candidate.id === modelId);
4100
+ return model === void 0 ? prev : {
4101
+ ...prev,
4102
+ [modelId]: formatCapacity$2(model.defaultContextWindow)
4103
+ };
4104
+ });
4105
+ notifyChange();
4106
+ } catch (err) {
4107
+ setError(err instanceof Error ? err.message : String(err));
4108
+ } finally {
4109
+ setSavingModel(null);
4110
+ }
4111
+ };
4112
+ /** Clear every stored override, including models the picker no longer shows. */
4113
+ const handleResetAllContextWindows = async () => {
4114
+ const models = Object.keys(status?.contextWindowOverrides ?? {});
4115
+ if (models.length === 0) return;
4116
+ if (typeof window !== "undefined" && !window.confirm(t.contextWindowResetAllConfirm)) return;
4117
+ try {
4118
+ setBusy("context");
4119
+ setError(null);
4120
+ const updated = await fetchApi$7("/settings", {
4121
+ method: "POST",
4122
+ body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
4123
+ });
4124
+ setStatus(updated);
4125
+ setContextDrafts(contextDraftsFor$2(updated));
4126
+ notifyChange();
4127
+ } catch (err) {
4128
+ setError(err instanceof Error ? err.message : String(err));
4129
+ } finally {
4130
+ setBusy(null);
4131
+ }
4132
+ };
4133
+ const contextModels = status?.models.filter((model) => model.enabled) ?? [];
4134
+ const overrideCount = Object.keys(status?.contextWindowOverrides ?? {}).length;
3853
4135
  if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3854
4136
  className: "dsha-page",
3855
4137
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -3928,7 +4210,7 @@ window.__ModuleLoader__.load({
3928
4210
  children: t.codeExpires
3929
4211
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3930
4212
  className: "dsha-value",
3931
- children: formatDate$1(flow?.expiresAt)
4213
+ children: formatDate$2(flow?.expiresAt)
3932
4214
  })]
3933
4215
  }),
3934
4216
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -4196,42 +4478,65 @@ window.__ModuleLoader__.load({
4196
4478
  className: "dsha-muted",
4197
4479
  children: t.contextWindowHint
4198
4480
  }),
4199
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4481
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4200
4482
  className: "dsha-context-settings",
4201
- children: status?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4202
- className: "dsha-context-row",
4203
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4204
- title: model.id,
4205
- children: [model.name, model.defaultContextWindow < model.contextWindow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4206
- className: "dsha-model-meta",
4207
- children: formatCapacity$1(model.contextWindow)
4208
- })]
4209
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4210
- className: "dsha-capacity-control",
4211
- children: [
4212
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4213
- type: "text",
4214
- "aria-label": `${model.name} context window`,
4215
- value: contextDrafts[model.id] ?? "",
4216
- onChange: (event) => setContextDrafts({
4217
- ...contextDrafts,
4218
- [model.id]: event.currentTarget.value
4483
+ children: [
4484
+ contextModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4485
+ className: "dsha-muted",
4486
+ children: t.contextWindowNoneEnabled
4487
+ }),
4488
+ contextModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4489
+ className: "dsha-context-row",
4490
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4491
+ title: model.id,
4492
+ children: [model.name, model.defaultContextWindow < model.contextWindow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4493
+ className: "dsha-model-meta",
4494
+ children: formatCapacity$2(model.contextWindow)
4495
+ })]
4496
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4497
+ className: "dsha-capacity-control",
4498
+ children: [
4499
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4500
+ type: "text",
4501
+ "aria-label": `${model.name} context window`,
4502
+ value: contextDrafts[model.id] ?? "",
4503
+ onChange: (event) => setContextDrafts({
4504
+ ...contextDrafts,
4505
+ [model.id]: event.currentTarget.value
4506
+ }),
4507
+ onKeyDown: (event) => {
4508
+ if (event.key === "Enter") handleSaveContextWindow(model.id);
4509
+ }
4219
4510
  }),
4220
- onKeyDown: (event) => {
4221
- if (event.key === "Enter") handleSaveContextWindow(model.id);
4222
- }
4223
- }),
4224
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
4225
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4226
- type: "button",
4227
- className: "dsha-context-save",
4228
- disabled: savingModel === model.id,
4229
- onClick: () => void handleSaveContextWindow(model.id),
4230
- children: savingModel === model.id ? t.saving : t.save
4231
- })
4232
- ]
4233
- })]
4234
- }, model.id))
4511
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
4512
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4513
+ type: "button",
4514
+ className: "dsha-context-save",
4515
+ disabled: savingModel === model.id,
4516
+ onClick: () => void handleSaveContextWindow(model.id),
4517
+ children: savingModel === model.id ? t.saving : t.save
4518
+ }),
4519
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4520
+ type: "button",
4521
+ className: "dsha-context-save dsha-context-reset",
4522
+ "aria-label": `${model.name} ${t.contextWindowReset}`,
4523
+ disabled: savingModel === model.id || status?.contextWindowOverrides[model.id] === void 0,
4524
+ onClick: () => void handleResetContextWindow(model.id),
4525
+ children: t.contextWindowReset
4526
+ })
4527
+ ]
4528
+ })]
4529
+ }, model.id)),
4530
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4531
+ className: "dsha-actions",
4532
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4533
+ className: "dsha-btn",
4534
+ disabled: busy !== null || overrideCount === 0,
4535
+ onClick: () => void handleResetAllContextWindows(),
4536
+ children: t.contextWindowResetAll
4537
+ })
4538
+ })
4539
+ ]
4235
4540
  })
4236
4541
  ]
4237
4542
  }),
@@ -4289,7 +4594,7 @@ window.__ModuleLoader__.load({
4289
4594
  window.limit ?? "—",
4290
4595
  " ",
4291
4596
  t.requests
4292
- ] }), window.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.resetAt.replace("{time}", formatReset$1(window.resetsAt)) })]
4597
+ ] }), window.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.resetAt.replace("{time}", formatReset$2(window.resetsAt)) })]
4293
4598
  })
4294
4599
  ]
4295
4600
  }, window.id);
@@ -4341,7 +4646,7 @@ window.__ModuleLoader__.load({
4341
4646
  //#endregion
4342
4647
  //#region src/client/workbuddy/locales.ts
4343
4648
  const NS_WORKBUDDY = "dsh-workbuddy";
4344
- const zh$1 = {
4649
+ const zh$2 = {
4345
4650
  title: "WorkBuddy",
4346
4651
  pageDesc: "复用本机 CodeBuddy 桌面端登录态,管理 WorkBuddy(CodeBuddy 订阅)模型、上下文窗口与额度。",
4347
4652
  account: "账号",
@@ -4404,6 +4709,10 @@ window.__ModuleLoader__.load({
4404
4709
  defaultEffortKept: "已保存的档位不被当前任何模型支持,已保留但不会生效。",
4405
4710
  contextWindowSection: "模型上下文窗口",
4406
4711
  contextWindowHint: "默认值来自订阅网关的模型目录(每个模型的真实上下文上限);可覆盖为自定义容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
4712
+ contextWindowReset: "恢复默认",
4713
+ contextWindowResetAll: "全部恢复默认",
4714
+ contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
4715
+ contextWindowNoneEnabled: "还没有勾选任何模型。在上方勾选后,这里会出现该模型的上下文窗口设置。",
4407
4716
  save: "保存",
4408
4717
  saved: "已保存",
4409
4718
  saving: "保存中...",
@@ -4419,9 +4728,19 @@ window.__ModuleLoader__.load({
4419
4728
  updatedAt: "更新时间:{time}",
4420
4729
  loading: "加载中...",
4421
4730
  credits: "credits",
4422
- composerLabel: "额度"
4731
+ composerLabel: "额度",
4732
+ dailyCheckin: "每日签到",
4733
+ checkinHint: "仅国区账号参与;DSH 启动时自动签到一次,运行期间每 10 分钟补检,进程关闭的当天不会签到。",
4734
+ checkinAuto: "自动签到",
4735
+ checkinToday: "今日已签 {done}/{total}",
4736
+ checkinSkipped: "{count} 个无签到活动",
4737
+ checkinFailed: "{count} 个失败",
4738
+ checkinLastRun: "上次运行:{time}",
4739
+ checkinNever: "尚未运行",
4740
+ checkinNow: "立即签到",
4741
+ checkinRunning: "签到中…"
4423
4742
  };
4424
- const en$1 = {
4743
+ const en$2 = {
4425
4744
  title: "WorkBuddy",
4426
4745
  pageDesc: "Reuse the local CodeBuddy desktop sign-in to manage WorkBuddy (CodeBuddy subscription) models, context windows, and quota.",
4427
4746
  account: "Account",
@@ -4484,6 +4803,10 @@ window.__ModuleLoader__.load({
4484
4803
  defaultEffortKept: "The saved level is not supported by any current model; it is kept but has no effect.",
4485
4804
  contextWindowSection: "Model context window",
4486
4805
  contextWindowHint: "Defaults come from the subscription gateway’s own catalog (each model’s real context cap); override one with the capacity DSH should use for compaction and overflow decisions (e.g., 1M, 512K, 200K).",
4806
+ contextWindowReset: "Restore default",
4807
+ contextWindowResetAll: "Restore all defaults",
4808
+ contextWindowResetAllConfirm: "Restore every changed model context window to its default?",
4809
+ contextWindowNoneEnabled: "No model is checked yet. Check one above and its context window setting appears here.",
4487
4810
  save: "Save",
4488
4811
  saved: "Saved",
4489
4812
  saving: "Saving...",
@@ -4499,13 +4822,23 @@ window.__ModuleLoader__.load({
4499
4822
  updatedAt: "Updated at: {time}",
4500
4823
  loading: "Loading...",
4501
4824
  credits: "credits",
4502
- composerLabel: "Quota"
4825
+ composerLabel: "Quota",
4826
+ dailyCheckin: "Daily check-in",
4827
+ checkinHint: "CN-region accounts only. The host signs in once at startup and re-checks every 10 minutes while running; a day the process never runs is not signed.",
4828
+ checkinAuto: "Auto check-in",
4829
+ checkinToday: "Checked in today {done}/{total}",
4830
+ checkinSkipped: "{count} with no activity",
4831
+ checkinFailed: "{count} failed",
4832
+ checkinLastRun: "Last run: {time}",
4833
+ checkinNever: "Never run",
4834
+ checkinNow: "Check in now",
4835
+ checkinRunning: "Checking in…"
4503
4836
  };
4504
- const dictionaries$1 = {
4505
- zh: zh$1,
4506
- "zh-CN": zh$1,
4507
- en: en$1,
4508
- "en-US": en$1
4837
+ const dictionaries$2 = {
4838
+ zh: zh$2,
4839
+ "zh-CN": zh$2,
4840
+ en: en$2,
4841
+ "en-US": en$2
4509
4842
  };
4510
4843
  //#endregion
4511
4844
  //#region src/client/workbuddy/WorkBuddySection.tsx
@@ -4513,7 +4846,7 @@ window.__ModuleLoader__.load({
4513
4846
  * Display label per reasoning level. The locale dictionary only accepts flat
4514
4847
  * string values, so this nested table lives with the control that renders it.
4515
4848
  */
4516
- const EFFORT_LABELS = {
4849
+ const EFFORT_LABELS$1 = {
4517
4850
  minimal: "Minimal",
4518
4851
  low: "Low",
4519
4852
  medium: "Medium",
@@ -4521,7 +4854,7 @@ window.__ModuleLoader__.load({
4521
4854
  xhigh: "X-High",
4522
4855
  max: "Max"
4523
4856
  };
4524
- const API$4 = "/workbuddy/api";
4857
+ const API$6 = "/workbuddy/api";
4525
4858
  /**
4526
4859
  * The shared card's label set.
4527
4860
  *
@@ -4547,8 +4880,8 @@ window.__ModuleLoader__.load({
4547
4880
  * process (a stale Host has no route to answer), so the error is reported as
4548
4881
  * such instead of as a credential problem.
4549
4882
  */
4550
- async function fetchApi$4(path, options) {
4551
- const res = await fetch(`${API$4}${path}`, {
4883
+ async function fetchApi$6(path, options) {
4884
+ const res = await fetch(`${API$6}${path}`, {
4552
4885
  ...options,
4553
4886
  headers: {
4554
4887
  "Content-Type": "application/json",
@@ -4567,19 +4900,29 @@ window.__ModuleLoader__.load({
4567
4900
  return json.value;
4568
4901
  }
4569
4902
  /** Parse "1M", "512K", "200000" into a positive integer token count. */
4570
- function parsePositiveCapacity(value) {
4903
+ function parsePositiveCapacity$1(value) {
4571
4904
  const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
4572
4905
  if (matched === null) return null;
4573
4906
  const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
4574
4907
  const parsed = Number(matched[1]) * multiplier;
4575
4908
  return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
4576
4909
  }
4577
- function formatCapacity(value) {
4910
+ function formatCapacity$1(value) {
4578
4911
  if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
4579
4912
  if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
4580
4913
  return String(value);
4581
4914
  }
4582
- function formatDate(ms) {
4915
+ /**
4916
+ * Seed one draft per model from a status payload. Also run after a model
4917
+ * toggle: a model that was just enabled has no draft yet, and the context
4918
+ * window section only renders enabled models.
4919
+ */
4920
+ function contextDraftsFor$1(status) {
4921
+ const drafts = {};
4922
+ for (const model of status.models) drafts[model.id] = formatCapacity$1(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
4923
+ return drafts;
4924
+ }
4925
+ function formatDate$1(ms) {
4583
4926
  if (ms === void 0 || ms === null || ms <= 0) return "—";
4584
4927
  try {
4585
4928
  return new Intl.DateTimeFormat(void 0, {
@@ -4590,7 +4933,7 @@ window.__ModuleLoader__.load({
4590
4933
  return "—";
4591
4934
  }
4592
4935
  }
4593
- function formatReset(resetsAt) {
4936
+ function formatReset$1(resetsAt) {
4594
4937
  if (resetsAt === void 0 || resetsAt === null || resetsAt <= 0) return "";
4595
4938
  const diff = resetsAt - Date.now();
4596
4939
  if (diff <= 0) return "now";
@@ -4667,7 +5010,7 @@ window.__ModuleLoader__.load({
4667
5010
  const loginTimeoutRef = (0, react.useRef)(null);
4668
5011
  const [contextDrafts, setContextDrafts] = (0, react.useState)({});
4669
5012
  const [savingModel, setSavingModel] = (0, react.useState)(null);
4670
- const t = zh$1;
5013
+ const t = zh$2;
4671
5014
  const notifyChange = (0, react.useCallback)(() => {
4672
5015
  onModelChange?.();
4673
5016
  loadModelDirectory?.();
@@ -4679,12 +5022,10 @@ window.__ModuleLoader__.load({
4679
5022
  const loadStatus = (0, react.useCallback)(async (quiet = false) => {
4680
5023
  if (!quiet) setError(null);
4681
5024
  try {
4682
- const normalized = normalizeStatus(await fetchApi$4("/status"));
5025
+ const normalized = normalizeStatus(await fetchApi$6("/status"));
4683
5026
  setStatus(normalized);
4684
5027
  setStatusFailed(false);
4685
- const drafts = {};
4686
- for (const model of normalized.models) drafts[model.id] = formatCapacity(normalized.contextWindowOverrides[model.id] || model.defaultContextWindow);
4687
- setContextDrafts(drafts);
5028
+ setContextDrafts(contextDraftsFor$1(normalized));
4688
5029
  } catch (err) {
4689
5030
  setStatusFailed(true);
4690
5031
  if (!quiet) setError(err instanceof Error ? err.message : String(err));
@@ -4708,7 +5049,7 @@ window.__ModuleLoader__.load({
4708
5049
  try {
4709
5050
  setBusy("rescan");
4710
5051
  setError(null);
4711
- const updated = await fetchApi$4("/rescan", { method: "POST" });
5052
+ const updated = await fetchApi$6("/rescan", { method: "POST" });
4712
5053
  setStatus(normalizeStatus(updated));
4713
5054
  notifyChange();
4714
5055
  } catch (err) {
@@ -4722,7 +5063,7 @@ window.__ModuleLoader__.load({
4722
5063
  setBusy(`login:${region}`);
4723
5064
  setError(null);
4724
5065
  setLoginProgress(t.loginWaiting);
4725
- const flow = await fetchApi$4("/accounts/login", {
5066
+ const flow = await fetchApi$6("/accounts/login", {
4726
5067
  method: "POST",
4727
5068
  body: JSON.stringify({ region })
4728
5069
  });
@@ -4732,7 +5073,7 @@ window.__ModuleLoader__.load({
4732
5073
  const timer = window.setInterval(() => {
4733
5074
  (async () => {
4734
5075
  try {
4735
- const poll = await fetchApi$4("/accounts/login/status");
5076
+ const poll = await fetchApi$6("/accounts/login/status");
4736
5077
  if (poll.progress) setLoginProgress(poll.progress);
4737
5078
  if (poll.status === "complete") {
4738
5079
  window.clearInterval(timer);
@@ -4741,7 +5082,7 @@ window.__ModuleLoader__.load({
4741
5082
  loginTimeoutRef.current = null;
4742
5083
  setBusy(null);
4743
5084
  setLoginProgress(null);
4744
- if (poll.accountId) await fetchApi$4("/settings", {
5085
+ if (poll.accountId) await fetchApi$6("/settings", {
4745
5086
  method: "POST",
4746
5087
  body: JSON.stringify({ selectedAccountId: poll.accountId })
4747
5088
  });
@@ -4781,7 +5122,7 @@ window.__ModuleLoader__.load({
4781
5122
  try {
4782
5123
  setBusy(`${action}:${accountId}`);
4783
5124
  setError(null);
4784
- const updated = await fetchApi$4("/accounts/action", {
5125
+ const updated = await fetchApi$6("/accounts/action", {
4785
5126
  method: "POST",
4786
5127
  body: JSON.stringify({
4787
5128
  action,
@@ -4804,7 +5145,7 @@ window.__ModuleLoader__.load({
4804
5145
  try {
4805
5146
  setBusy("strategy");
4806
5147
  setError(null);
4807
- const updated = await fetchApi$4("/accounts/strategy", {
5148
+ const updated = await fetchApi$6("/accounts/strategy", {
4808
5149
  method: "POST",
4809
5150
  body: JSON.stringify({ strategy })
4810
5151
  });
@@ -4819,7 +5160,7 @@ window.__ModuleLoader__.load({
4819
5160
  try {
4820
5161
  setBusy("connection");
4821
5162
  setError(null);
4822
- setConnection(await fetchApi$4("/connection/test", { method: "POST" }));
5163
+ setConnection(await fetchApi$6("/connection/test", { method: "POST" }));
4823
5164
  } catch (err) {
4824
5165
  setError(err instanceof Error ? err.message : String(err));
4825
5166
  } finally {
@@ -4830,7 +5171,7 @@ window.__ModuleLoader__.load({
4830
5171
  try {
4831
5172
  setBusy("quota");
4832
5173
  setError(null);
4833
- const updated = await fetchApi$4("/quota", { method: "POST" });
5174
+ const updated = await fetchApi$6("/quota", { method: "POST" });
4834
5175
  setStatus(updated);
4835
5176
  } catch (err) {
4836
5177
  setError(err instanceof Error ? err.message : String(err));
@@ -4838,11 +5179,38 @@ window.__ModuleLoader__.load({
4838
5179
  setBusy(null);
4839
5180
  }
4840
5181
  };
5182
+ const handleCheckinNow = async () => {
5183
+ try {
5184
+ setBusy("checkin");
5185
+ setError(null);
5186
+ const updated = await fetchApi$6("/checkin/now", { method: "POST" });
5187
+ setStatus(normalizeStatus(updated));
5188
+ } catch (err) {
5189
+ setError(err instanceof Error ? err.message : String(err));
5190
+ } finally {
5191
+ setBusy(null);
5192
+ }
5193
+ };
5194
+ const handleCheckinPatch = async (checkin) => {
5195
+ try {
5196
+ setBusy("checkin");
5197
+ setError(null);
5198
+ const updated = await fetchApi$6("/settings", {
5199
+ method: "POST",
5200
+ body: JSON.stringify({ checkin })
5201
+ });
5202
+ setStatus(normalizeStatus(updated));
5203
+ } catch (err) {
5204
+ setError(err instanceof Error ? err.message : String(err));
5205
+ } finally {
5206
+ setBusy(null);
5207
+ }
5208
+ };
4841
5209
  const toggleEnabled = async (enabled) => {
4842
5210
  try {
4843
5211
  setBusy("enabled");
4844
5212
  setError(null);
4845
- const updated = await fetchApi$4("/settings", {
5213
+ const updated = await fetchApi$6("/settings", {
4846
5214
  method: "POST",
4847
5215
  body: JSON.stringify({ enabled })
4848
5216
  });
@@ -4861,11 +5229,12 @@ window.__ModuleLoader__.load({
4861
5229
  try {
4862
5230
  setBusy(`model:${modelId}`);
4863
5231
  setError(null);
4864
- const updated = await fetchApi$4("/settings", {
5232
+ const normalized = normalizeStatus(await fetchApi$6("/settings", {
4865
5233
  method: "POST",
4866
5234
  body: JSON.stringify({ enabledModelIds: next })
4867
- });
4868
- setStatus(updated);
5235
+ }));
5236
+ setStatus(normalized);
5237
+ setContextDrafts(contextDraftsFor$1(normalized));
4869
5238
  notifyChange();
4870
5239
  } catch (err) {
4871
5240
  setError(err instanceof Error ? err.message : String(err));
@@ -4878,11 +5247,12 @@ window.__ModuleLoader__.load({
4878
5247
  try {
4879
5248
  setBusy("models-all");
4880
5249
  setError(null);
4881
- const updated = await fetchApi$4("/settings", {
5250
+ const normalized = normalizeStatus(await fetchApi$6("/settings", {
4882
5251
  method: "POST",
4883
5252
  body: JSON.stringify({ enabledModelIds: enabled ? status.models.map((model) => model.id) : [] })
4884
- });
4885
- setStatus(updated);
5253
+ }));
5254
+ setStatus(normalized);
5255
+ setContextDrafts(contextDraftsFor$1(normalized));
4886
5256
  notifyChange();
4887
5257
  } catch (err) {
4888
5258
  setError(err instanceof Error ? err.message : String(err));
@@ -4894,7 +5264,7 @@ window.__ModuleLoader__.load({
4894
5264
  try {
4895
5265
  setBusy("effort");
4896
5266
  setError(null);
4897
- const updated = await fetchApi$4("/settings", {
5267
+ const updated = await fetchApi$6("/settings", {
4898
5268
  method: "POST",
4899
5269
  body: JSON.stringify({ defaultReasoningEffort: effort })
4900
5270
  });
@@ -4910,16 +5280,9 @@ window.__ModuleLoader__.load({
4910
5280
  try {
4911
5281
  setBusy("catalog");
4912
5282
  setError(null);
4913
- const updated = await fetchApi$4("/catalog/refresh", { method: "POST" });
4914
- const normalized = {
4915
- ...updated,
4916
- models: Array.isArray(updated?.models) ? updated.models : [],
4917
- contextWindowOverrides: updated?.contextWindowOverrides ?? {}
4918
- };
5283
+ const normalized = normalizeStatus(await fetchApi$6("/catalog/refresh", { method: "POST" }));
4919
5284
  setStatus(normalized);
4920
- const drafts = {};
4921
- for (const model of normalized.models) drafts[model.id] = formatCapacity(normalized.contextWindowOverrides[model.id] || model.defaultContextWindow);
4922
- setContextDrafts(drafts);
5285
+ setContextDrafts(contextDraftsFor$1(normalized));
4923
5286
  notifyChange();
4924
5287
  } catch (err) {
4925
5288
  setError(err instanceof Error ? err.message : String(err));
@@ -4929,7 +5292,7 @@ window.__ModuleLoader__.load({
4929
5292
  };
4930
5293
  const handleSaveContextWindow = async (modelId) => {
4931
5294
  const raw = contextDrafts[modelId] || "";
4932
- const parsed = parsePositiveCapacity(raw);
5295
+ const parsed = parsePositiveCapacity$1(raw);
4933
5296
  if (parsed === null) {
4934
5297
  setError(`Invalid context capacity: ${raw}`);
4935
5298
  return;
@@ -4937,15 +5300,39 @@ window.__ModuleLoader__.load({
4937
5300
  try {
4938
5301
  setSavingModel(modelId);
4939
5302
  setError(null);
4940
- const updated = await fetchApi$4("/settings", {
5303
+ const updated = await fetchApi$6("/settings", {
4941
5304
  method: "POST",
4942
5305
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
4943
5306
  });
4944
5307
  setStatus(updated);
4945
5308
  setContextDrafts((prev) => ({
4946
5309
  ...prev,
4947
- [modelId]: formatCapacity(parsed)
5310
+ [modelId]: formatCapacity$1(parsed)
5311
+ }));
5312
+ notifyChange();
5313
+ } catch (err) {
5314
+ setError(err instanceof Error ? err.message : String(err));
5315
+ } finally {
5316
+ setSavingModel(null);
5317
+ }
5318
+ };
5319
+ /** Clear one override; the row falls back to the catalog length. */
5320
+ const handleResetContextWindow = async (modelId) => {
5321
+ try {
5322
+ setSavingModel(modelId);
5323
+ setError(null);
5324
+ const updated = normalizeStatus(await fetchApi$6("/settings", {
5325
+ method: "POST",
5326
+ body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
4948
5327
  }));
5328
+ setStatus(updated);
5329
+ setContextDrafts((prev) => {
5330
+ const model = updated.models.find((candidate) => candidate.id === modelId);
5331
+ return model === void 0 ? prev : {
5332
+ ...prev,
5333
+ [modelId]: formatCapacity$1(model.defaultContextWindow)
5334
+ };
5335
+ });
4949
5336
  notifyChange();
4950
5337
  } catch (err) {
4951
5338
  setError(err instanceof Error ? err.message : String(err));
@@ -4953,6 +5340,29 @@ window.__ModuleLoader__.load({
4953
5340
  setSavingModel(null);
4954
5341
  }
4955
5342
  };
5343
+ /** Clear every stored override, including models the picker no longer shows. */
5344
+ const handleResetAllContextWindows = async () => {
5345
+ const models = Object.keys(status?.contextWindowOverrides ?? {});
5346
+ if (models.length === 0) return;
5347
+ if (!window.confirm(t.contextWindowResetAllConfirm)) return;
5348
+ try {
5349
+ setBusy("context");
5350
+ setError(null);
5351
+ const updated = normalizeStatus(await fetchApi$6("/settings", {
5352
+ method: "POST",
5353
+ body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
5354
+ }));
5355
+ setStatus(updated);
5356
+ setContextDrafts(contextDraftsFor$1(updated));
5357
+ notifyChange();
5358
+ } catch (err) {
5359
+ setError(err instanceof Error ? err.message : String(err));
5360
+ } finally {
5361
+ setBusy(null);
5362
+ }
5363
+ };
5364
+ const contextModels = status?.models.filter((model) => model.enabled) ?? [];
5365
+ const overrideCount = Object.keys(status?.contextWindowOverrides ?? {}).length;
4956
5366
  if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4957
5367
  className: "dsha-page",
4958
5368
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -5066,6 +5476,57 @@ window.__ModuleLoader__.load({
5066
5476
  })
5067
5477
  ]
5068
5478
  }),
5479
+ status?.checkin != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5480
+ className: "dsha-group",
5481
+ children: [
5482
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5483
+ className: "dsha-grouphead",
5484
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.dailyCheckin })
5485
+ }),
5486
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5487
+ className: "dsha-muted",
5488
+ children: t.checkinHint
5489
+ }),
5490
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5491
+ className: "dsha-row",
5492
+ style: { marginBottom: 8 },
5493
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5494
+ className: "dsha-label",
5495
+ style: { fontWeight: 600 },
5496
+ children: t.checkinAuto
5497
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5498
+ type: "checkbox",
5499
+ checked: status.checkin.enabled,
5500
+ disabled: busy !== null,
5501
+ onChange: (event) => void handleCheckinPatch({ enabled: event.currentTarget.checked })
5502
+ })]
5503
+ }),
5504
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5505
+ className: "dsha-row",
5506
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5507
+ className: "dsha-label",
5508
+ children: t.dailyCheckin
5509
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5510
+ className: "dsha-value",
5511
+ children: [
5512
+ t.checkinToday.replace("{done}", String(status.checkin.doneToday)).replace("{total}", String(status.checkin.totalAccounts)),
5513
+ status.checkin.skippedToday > 0 ? ` · ${t.checkinSkipped.replace("{count}", String(status.checkin.skippedToday))}` : "",
5514
+ status.checkin.failedToday > 0 ? ` · ${t.checkinFailed.replace("{count}", String(status.checkin.failedToday))}` : "",
5515
+ ` · ${status.checkin.lastRunAt === null ? t.checkinNever : t.checkinLastRun.replace("{time}", new Date(status.checkin.lastRunAt).toLocaleString())}`
5516
+ ]
5517
+ })]
5518
+ }),
5519
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5520
+ className: "dsha-actions",
5521
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5522
+ className: "dsha-btn",
5523
+ disabled: busy !== null,
5524
+ onClick: () => void handleCheckinNow(),
5525
+ children: busy === "checkin" ? t.checkinRunning : t.checkinNow
5526
+ })
5527
+ })
5528
+ ]
5529
+ }) : null,
5069
5530
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5070
5531
  className: "dsha-group",
5071
5532
  children: [
@@ -5145,7 +5606,7 @@ window.__ModuleLoader__.load({
5145
5606
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
5146
5607
  title: [
5147
5608
  model.id,
5148
- formatCapacity(model.contextWindow),
5609
+ formatCapacity$1(model.contextWindow),
5149
5610
  model.supportsImage ? t.imageSupport : t.textOnly,
5150
5611
  ...model.reasoningEfforts && model.reasoningEfforts.length > 0 ? [model.reasoningEfforts.join("/")] : []
5151
5612
  ].join(" · "),
@@ -5209,11 +5670,11 @@ window.__ModuleLoader__.load({
5209
5670
  }),
5210
5671
  strayEffort !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
5211
5672
  value: strayEffort,
5212
- children: `${EFFORT_LABELS[strayEffort]} (${t.effortUnsupported})`
5673
+ children: `${EFFORT_LABELS$1[strayEffort]} (${t.effortUnsupported})`
5213
5674
  }) : null,
5214
5675
  effortChoices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
5215
5676
  value: choice.value,
5216
- children: choice.models.length === allModels.length ? EFFORT_LABELS[choice.value] : `${EFFORT_LABELS[choice.value]} (${choice.models.length}/${allModels.length})`
5677
+ children: choice.models.length === allModels.length ? EFFORT_LABELS$1[choice.value] : `${EFFORT_LABELS$1[choice.value]} (${choice.models.length}/${allModels.length})`
5217
5678
  }, choice.value))
5218
5679
  ]
5219
5680
  })]
@@ -5235,39 +5696,988 @@ window.__ModuleLoader__.load({
5235
5696
  className: "dsha-muted",
5236
5697
  children: t.contextWindowHint
5237
5698
  }),
5238
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5699
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5700
+ className: "dsha-context-settings",
5701
+ children: [
5702
+ contextModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5703
+ className: "dsha-muted",
5704
+ children: t.contextWindowNoneEnabled
5705
+ }),
5706
+ contextModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5707
+ className: "dsha-context-row",
5708
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5709
+ title: model.id,
5710
+ children: model.name
5711
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5712
+ className: "dsha-capacity-control",
5713
+ children: [
5714
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5715
+ type: "text",
5716
+ "aria-label": `${model.name} context window`,
5717
+ value: contextDrafts[model.id] ?? "",
5718
+ onChange: (event) => setContextDrafts({
5719
+ ...contextDrafts,
5720
+ [model.id]: event.currentTarget.value
5721
+ }),
5722
+ onKeyDown: (event) => {
5723
+ if (event.key === "Enter") handleSaveContextWindow(model.id);
5724
+ }
5725
+ }),
5726
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "tokens" }),
5727
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5728
+ type: "button",
5729
+ className: "dsha-context-save",
5730
+ disabled: savingModel === model.id,
5731
+ onClick: () => void handleSaveContextWindow(model.id),
5732
+ children: savingModel === model.id ? t.saving : t.save
5733
+ }),
5734
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5735
+ type: "button",
5736
+ className: "dsha-context-save dsha-context-reset",
5737
+ "aria-label": `${model.name} ${t.contextWindowReset}`,
5738
+ disabled: savingModel === model.id || status?.contextWindowOverrides[model.id] === void 0,
5739
+ onClick: () => void handleResetContextWindow(model.id),
5740
+ children: t.contextWindowReset
5741
+ })
5742
+ ]
5743
+ })]
5744
+ }, model.id)),
5745
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5746
+ className: "dsha-actions",
5747
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5748
+ className: "dsha-btn",
5749
+ disabled: busy !== null || overrideCount === 0,
5750
+ onClick: () => void handleResetAllContextWindows(),
5751
+ children: t.contextWindowResetAll
5752
+ })
5753
+ })
5754
+ ]
5755
+ })
5756
+ ]
5757
+ }),
5758
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5759
+ className: "dsha-group",
5760
+ children: [
5761
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5762
+ className: "dsha-grouphead",
5763
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5764
+ className: "dsha-btn",
5765
+ disabled: busy !== null || !authenticated,
5766
+ onClick: () => void handleRefreshQuota(),
5767
+ children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
5768
+ })]
5769
+ }),
5770
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5771
+ className: "dsha-muted",
5772
+ children: t.quotaDesc
5773
+ }),
5774
+ !authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5775
+ className: "dsha-empty",
5776
+ children: t.signedOut
5777
+ }) : quota === null || quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5778
+ className: "dsha-empty",
5779
+ children: busy === "quota" ? t.refreshingQuota : t.quotaEmpty
5780
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5781
+ className: "dsha-quota-card",
5782
+ children: [
5783
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5784
+ className: "dsha-quota-title",
5785
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota.packageName || t.quotaPackage }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.remainingCredits !== null ? `${quota.remainingCredits} ${t.credits}` : "—" })]
5786
+ }),
5787
+ quota.cycleUsedCredits !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5788
+ className: "dsha-row",
5789
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5790
+ className: "dsha-label",
5791
+ children: t.quotaCycle
5792
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5793
+ className: "dsha-value",
5794
+ children: [
5795
+ quota.cycleUsedCredits,
5796
+ quota.cycleCredits !== null ? ` / ${quota.cycleCredits}` : "",
5797
+ ` ${t.credits}`
5798
+ ]
5799
+ })]
5800
+ }),
5801
+ quota.cycleEndsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5802
+ className: "dsha-row",
5803
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5804
+ className: "dsha-label",
5805
+ children: t.quotaReset
5806
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5807
+ className: "dsha-value",
5808
+ children: [formatDate$1(quota.cycleEndsAt), formatReset$1(quota.cycleEndsAt) ? ` · ${formatReset$1(quota.cycleEndsAt)}` : ""]
5809
+ })]
5810
+ }),
5811
+ quota.meters.map((meter) => {
5812
+ const remaining = meter.remainingFraction;
5813
+ const percent = remaining === null ? null : Math.round(remaining * 100);
5814
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5815
+ className: "dsha-meter-wrap",
5816
+ children: [
5817
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5818
+ className: "dsha-meter-label",
5819
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meter.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: percent === null ? meter.limit ?? "—" : `${percent}% left` })]
5820
+ }),
5821
+ percent !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5822
+ className: "dsha-meter dsha-meter-green",
5823
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${percent}%` } })
5824
+ }),
5825
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5826
+ className: "dsha-meter-meta",
5827
+ children: [meter.used !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5828
+ meter.used,
5829
+ " / ",
5830
+ meter.limit ?? "—"
5831
+ ] }), meter.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5832
+ t.quotaReset,
5833
+ ": ",
5834
+ formatReset$1(meter.resetsAt)
5835
+ ] })]
5836
+ })
5837
+ ]
5838
+ }, meter.id);
5839
+ }),
5840
+ quota.meters.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5841
+ className: "dsha-empty",
5842
+ children: t.quotaEmpty
5843
+ }),
5844
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5845
+ className: "dsha-timestamp",
5846
+ children: t.updatedAt.replace("{time}", new Date(quota.fetchedAt).toLocaleString())
5847
+ })
5848
+ ]
5849
+ })
5850
+ ]
5851
+ }),
5852
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5853
+ className: "dsha-error",
5854
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: error })
5855
+ })
5856
+ ]
5857
+ });
5858
+ }
5859
+ //#endregion
5860
+ //#region src/shared/zhipu-contracts.ts
5861
+ /** Every level this route can name, in escalating order (the card's sort key). */
5862
+ const ZHIPU_REASONING_EFFORTS = [
5863
+ "low",
5864
+ "high",
5865
+ "max"
5866
+ ];
5867
+ ({
5868
+ none: 0,
5869
+ minimal: 1,
5870
+ low: 2,
5871
+ medium: 3,
5872
+ high: 4,
5873
+ xhigh: 5,
5874
+ max: 6
5875
+ }).high;
5876
+ //#endregion
5877
+ //#region src/client/zhipu/locales.ts
5878
+ const NS_ZHIPU = "dsh-zhipu";
5879
+ const zh$1 = {
5880
+ ...accountPoolZh,
5881
+ title: "GLM(智谱 Coding Plan)",
5882
+ pageDesc: "添加智谱 / Z.ai 的 GLM Coding Plan API Key,管理可用模型、上下文窗口与额度。",
5883
+ account: "账号",
5884
+ signedIn: "已登录",
5885
+ signedOut: "未登录",
5886
+ region: "区域",
5887
+ regionIntl: "国际区 (api.z.ai)",
5888
+ regionCn: "国区 (open.bigmodel.cn)",
5889
+ keyHint: "Key 尾号",
5890
+ plan: "套餐",
5891
+ planUnknown: "—",
5892
+ renews: "续费于",
5893
+ authenticatedAt: "添加时间",
5894
+ storage: "凭据存储",
5895
+ storageNotice: "API Key 由 Host 保存于本地加密存储,不会进入浏览器。",
5896
+ signOut: "注销",
5897
+ addKeySection: "添加 API Key",
5898
+ addKeyHint: "在对应开放平台的「API Keys」页创建 Key 后粘贴到此处。它必须来自你订阅 Coding Plan 的那个平台:国区 Key 与国际区 Key 互不通用,开放平台(/api/paas/v4)的通用 Key 在订阅接口上会被拒绝。",
5899
+ keyPlaceholder: "粘贴 GLM Coding Plan API Key",
5900
+ keySave: "保存并验证",
5901
+ keySaving: "验证中...",
5902
+ keySaved: "已保存",
5903
+ connection: "连接",
5904
+ provider: "Provider",
5905
+ providerValue: "GLM(智谱 Coding Plan)· zhipu-coding-plan",
5906
+ connectionState: "连接状态",
5907
+ connected: "已连接",
5908
+ untested: "未测试",
5909
+ testConnection: "测试连接",
5910
+ testingConnection: "测试中...",
5911
+ routeOwned: "模型路由由本插件提供",
5912
+ routeConflict: "模型路由已被其他 Provider 占用:{detail}。请在 DSH 设置中移除重复的 Provider 配置后重试。",
5913
+ modelsSection: "模型",
5914
+ enableProvider: "启用此供应商",
5915
+ modelsHint: "勾选后模型才会出现在对话页的模型选择列表中;全部取消勾选或关闭上方开关可在列表中隐藏该供应商。",
5916
+ refreshCatalog: "刷新模型目录",
5917
+ refreshingCatalog: "刷新中...",
5918
+ selectAll: "全选",
5919
+ unselectAll: "全不选",
5920
+ effectiveWindow: "有效窗口",
5921
+ enhanced: "增强功能",
5922
+ defaultReasoningEffort: "默认思考深度",
5923
+ defaultReasoningEffortHint: "仅对声明了思考档位的模型生效。上游只接受 low / high / max,其余档位会收敛到最近的可用档位后发出(不支持的档位会直接报错)。",
5924
+ defaultEffortAuto: "使用 Provider 默认值",
5925
+ contextWindowSection: "模型上下文窗口",
5926
+ contextWindowHint: "默认取该模型官方声明的上下文窗口;可覆盖为自定义容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
5927
+ contextWindowReset: "恢复默认",
5928
+ contextWindowResetAll: "全部恢复默认",
5929
+ contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
5930
+ contextWindowNoneEnabled: "还没有勾选任何模型。在上方勾选后,这里会出现该模型的上下文窗口设置。",
5931
+ save: "保存",
5932
+ saved: "已保存",
5933
+ saving: "保存中...",
5934
+ quotaSection: "用量与配额",
5935
+ quotaDesc: "数据来自 GLM Coding Plan 的用量接口,页面可见时最多每 60 秒刷新一次。Coding Plan 同时受 5 小时额度与每周额度限制。",
5936
+ refreshQuota: "刷新用量",
5937
+ refreshingQuota: "刷新中...",
5938
+ quotaEmpty: "暂无配额数据,点击「刷新用量」重试。",
5939
+ quotaUnavailable: "该账号没有可用的配额数据(通常是套餐未生效,或 Key 不属于 Coding Plan)。",
5940
+ quotaError: "配额读取失败",
5941
+ updatedAt: "更新时间:{time}",
5942
+ loading: "加载中...",
5943
+ tokens: "tokens",
5944
+ left: "剩余",
5945
+ resetAt: "重置于",
5946
+ now: "即将重置"
5947
+ };
5948
+ const en$1 = {
5949
+ ...accountPoolEn,
5950
+ title: "GLM (Zhipu Coding Plan)",
5951
+ pageDesc: "Add a GLM Coding Plan API key for Zhipu / Z.ai and manage models, context windows, and quota.",
5952
+ account: "Account",
5953
+ signedIn: "Signed in",
5954
+ signedOut: "Not signed in",
5955
+ region: "Region",
5956
+ regionIntl: "International (api.z.ai)",
5957
+ regionCn: "China (open.bigmodel.cn)",
5958
+ keyHint: "Key suffix",
5959
+ plan: "Plan",
5960
+ planUnknown: "—",
5961
+ renews: "renews",
5962
+ authenticatedAt: "Added at",
5963
+ storage: "Credential storage",
5964
+ storageNotice: "The API key is stored locally by the Host in encrypted storage and never reaches the browser.",
5965
+ signOut: "Sign out",
5966
+ addKeySection: "Add an API key",
5967
+ addKeyHint: "Create a key on the console’s API Keys page and paste it here. It must come from the platform your Coding Plan was bought on: China and international keys are not interchangeable, and a general open-platform key (/api/paas/v4) is rejected by the subscription surface.",
5968
+ keyPlaceholder: "Paste a GLM Coding Plan API key",
5969
+ keySave: "Save and verify",
5970
+ keySaving: "Verifying...",
5971
+ keySaved: "Saved",
5972
+ connection: "Connection",
5973
+ provider: "Provider",
5974
+ providerValue: "GLM (Zhipu Coding Plan) · zhipu-coding-plan",
5975
+ connectionState: "Connection state",
5976
+ connected: "Connected",
5977
+ untested: "Untested",
5978
+ testConnection: "Test connection",
5979
+ testingConnection: "Testing...",
5980
+ routeOwned: "This plugin serves the model route",
5981
+ routeConflict: "Another provider already owns the model route: {detail}. Remove the duplicate provider configuration in DSH settings and reload.",
5982
+ modelsSection: "Models",
5983
+ enableProvider: "Enable this provider",
5984
+ modelsHint: "Checked models appear in the DSH conversation model list; unchecking all or turning off the switch hides this provider.",
5985
+ refreshCatalog: "Refresh catalog",
5986
+ refreshingCatalog: "Refreshing...",
5987
+ selectAll: "Select all",
5988
+ unselectAll: "Deselect all",
5989
+ effectiveWindow: "Effective window",
5990
+ enhanced: "Enhanced features",
5991
+ defaultReasoningEffort: "Default reasoning effort",
5992
+ defaultReasoningEffortHint: "Applies only to models that declare a reasoning ladder. The provider accepts low / high / max; any other level is converged onto the nearest supported one before it is sent, because an unsupported level is rejected outright.",
5993
+ defaultEffortAuto: "Use provider default",
5994
+ contextWindowSection: "Model context window",
5995
+ contextWindowHint: "Defaults to the window the model itself declares; override it with the capacity DSH should use for compaction and overflow decisions (e.g., 1M, 512K, 200K).",
5996
+ contextWindowReset: "Restore default",
5997
+ contextWindowResetAll: "Restore all defaults",
5998
+ contextWindowResetAllConfirm: "Restore every changed model context window to its default?",
5999
+ contextWindowNoneEnabled: "No model is checked yet. Check one above and its context window setting appears here.",
6000
+ save: "Save",
6001
+ saved: "Saved",
6002
+ saving: "Saving...",
6003
+ quotaSection: "Usage & quota",
6004
+ quotaDesc: "Read from the GLM Coding Plan usage endpoints; refreshes at most once every 60 seconds while visible. A Coding Plan is bounded by both a 5-hour and a weekly allowance.",
6005
+ refreshQuota: "Refresh quota",
6006
+ refreshingQuota: "Refreshing...",
6007
+ quotaEmpty: "No quota data yet — use “Refresh quota” to retry.",
6008
+ quotaUnavailable: "This account reports no usable quota (usually an inactive plan, or a key that is not a Coding Plan key).",
6009
+ quotaError: "Quota lookup failed",
6010
+ updatedAt: "Updated at: {time}",
6011
+ loading: "Loading...",
6012
+ tokens: "tokens",
6013
+ left: "left",
6014
+ resetAt: "Resets at",
6015
+ now: "resetting now"
6016
+ };
6017
+ const dictionaries$1 = {
6018
+ zh: zh$1,
6019
+ "zh-CN": zh$1,
6020
+ en: en$1,
6021
+ "en-US": en$1
6022
+ };
6023
+ //#endregion
6024
+ //#region src/client/zhipu/ZhipuSection.tsx
6025
+ /**
6026
+ * Display label per reasoning level. The locale dictionary only accepts flat
6027
+ * string values, so this table lives with the control that renders it.
6028
+ */
6029
+ const EFFORT_LABELS = {
6030
+ low: "Low",
6031
+ high: "High",
6032
+ max: "Max"
6033
+ };
6034
+ const API$5 = "/zhipu/api";
6035
+ async function fetchApi$5(path, options) {
6036
+ const res = await fetch(`${API$5}${path}`, {
6037
+ ...options,
6038
+ headers: {
6039
+ "Content-Type": "application/json",
6040
+ ...options?.headers
6041
+ }
6042
+ });
6043
+ const json = await res.json();
6044
+ if (!res.ok || !json.ok) throw new Error(json.error || `HTTP ${res.status}`);
6045
+ return json.value;
6046
+ }
6047
+ /** Parse "1M", "512K", "200000" into a positive integer token count. */
6048
+ function parsePositiveCapacity(value) {
6049
+ const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
6050
+ if (matched === null) return null;
6051
+ const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
6052
+ const parsed = Number(matched[1]) * multiplier;
6053
+ return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
6054
+ }
6055
+ function formatCapacity(value) {
6056
+ if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
6057
+ if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
6058
+ return String(value);
6059
+ }
6060
+ /**
6061
+ * Seed one draft per model from a status payload. Also run after a model
6062
+ * toggle: a model that was just enabled has no draft yet, and the context
6063
+ * window section only renders enabled models.
6064
+ */
6065
+ function contextDraftsFor(status) {
6066
+ const drafts = {};
6067
+ for (const model of status.models) drafts[model.id] = formatCapacity(status.contextWindowOverrides[model.id] || model.defaultContextWindow);
6068
+ return drafts;
6069
+ }
6070
+ function formatDate(ms) {
6071
+ if (ms === void 0 || ms === null || ms <= 0) return "—";
6072
+ try {
6073
+ return new Intl.DateTimeFormat(void 0, {
6074
+ dateStyle: "medium",
6075
+ timeStyle: "short"
6076
+ }).format(ms);
6077
+ } catch {
6078
+ return "—";
6079
+ }
6080
+ }
6081
+ function formatReset(resetsAt, nowLabel = "now") {
6082
+ if (resetsAt === void 0 || resetsAt === null || resetsAt <= 0) return "";
6083
+ const diff = resetsAt - Date.now();
6084
+ if (diff <= 0) return nowLabel;
6085
+ const mins = Math.floor(diff / 6e4);
6086
+ const hours = Math.floor(mins / 60);
6087
+ const days = Math.floor(hours / 24);
6088
+ if (days > 0) return `${days}d ${hours % 24}h`;
6089
+ if (hours > 0) return `${hours}h ${mins % 60}m`;
6090
+ return `${mins}m`;
6091
+ }
6092
+ function ZhipuSection({ onModelChange, loadModelDirectory }) {
6093
+ const [status, setStatus] = (0, react.useState)(null);
6094
+ const [loading, setLoading] = (0, react.useState)(true);
6095
+ const [busy, setBusy] = (0, react.useState)(null);
6096
+ const [error, setError] = (0, react.useState)(null);
6097
+ const [contextDrafts, setContextDrafts] = (0, react.useState)({});
6098
+ const [savingModel, setSavingModel] = (0, react.useState)(null);
6099
+ const [apiKey, setApiKey] = (0, react.useState)("");
6100
+ const [region, setRegion] = (0, react.useState)("intl");
6101
+ const t = zh$1;
6102
+ const notifyChange = (0, react.useCallback)(() => {
6103
+ onModelChange?.();
6104
+ loadModelDirectory?.();
6105
+ }, [onModelChange, loadModelDirectory]);
6106
+ const loadStatus = (0, react.useCallback)(async (quiet = false) => {
6107
+ if (!quiet) setError(null);
6108
+ try {
6109
+ const data = await fetchApi$5("/status");
6110
+ setStatus(data);
6111
+ setContextDrafts(contextDraftsFor(data));
6112
+ } catch (err) {
6113
+ if (!quiet) setError(err instanceof Error ? err.message : String(err));
6114
+ } finally {
6115
+ setLoading(false);
6116
+ }
6117
+ }, []);
6118
+ (0, react.useEffect)(() => {
6119
+ loadStatus();
6120
+ const refreshWhenVisible = () => {
6121
+ if (document.visibilityState === "visible") loadStatus(true);
6122
+ };
6123
+ document.addEventListener("visibilitychange", refreshWhenVisible);
6124
+ const timer = window.setInterval(refreshWhenVisible, 6e4);
6125
+ return () => {
6126
+ window.clearInterval(timer);
6127
+ document.removeEventListener("visibilitychange", refreshWhenVisible);
6128
+ };
6129
+ }, [loadStatus]);
6130
+ /**
6131
+ * Save one pasted key.
6132
+ *
6133
+ * The host verifies it against the deployment before persisting, so a key
6134
+ * from the wrong console fails here with a message naming the console it
6135
+ * belongs to rather than inside a conversation later.
6136
+ */
6137
+ const handleAddKey = async () => {
6138
+ try {
6139
+ setBusy("apikey");
6140
+ setError(null);
6141
+ const updated = await fetchApi$5("/accounts/add", {
6142
+ method: "POST",
6143
+ body: JSON.stringify({
6144
+ apiKey,
6145
+ region
6146
+ })
6147
+ });
6148
+ setStatus(updated);
6149
+ setContextDrafts(contextDraftsFor(updated));
6150
+ setApiKey("");
6151
+ notifyChange();
6152
+ } catch (err) {
6153
+ setError(err instanceof Error ? err.message : String(err));
6154
+ } finally {
6155
+ setBusy(null);
6156
+ }
6157
+ };
6158
+ /** One account-level action on the shared pool card. */
6159
+ const handleAccountAction = async (action, accountId) => {
6160
+ try {
6161
+ setBusy(`${action}-${accountId}`);
6162
+ setError(null);
6163
+ const updated = await fetchApi$5("/accounts/action", {
6164
+ method: "POST",
6165
+ body: JSON.stringify({
6166
+ action,
6167
+ accountId
6168
+ })
6169
+ });
6170
+ setStatus(updated);
6171
+ notifyChange();
6172
+ } catch (err) {
6173
+ setError(err instanceof Error ? err.message : String(err));
6174
+ } finally {
6175
+ setBusy(null);
6176
+ }
6177
+ };
6178
+ const handleSetStrategy = async (strategy) => {
6179
+ try {
6180
+ setBusy("strategy");
6181
+ setError(null);
6182
+ const updated = await fetchApi$5("/accounts/action", {
6183
+ method: "POST",
6184
+ body: JSON.stringify({
6185
+ action: "strategy",
6186
+ strategy
6187
+ })
6188
+ });
6189
+ setStatus(updated);
6190
+ } catch (err) {
6191
+ setError(err instanceof Error ? err.message : String(err));
6192
+ } finally {
6193
+ setBusy(null);
6194
+ }
6195
+ };
6196
+ const handleRefreshQuota = async () => {
6197
+ try {
6198
+ setBusy("quota");
6199
+ setError(null);
6200
+ const updated = await fetchApi$5("/quota", { method: "POST" });
6201
+ setStatus(updated);
6202
+ } catch (err) {
6203
+ setError(err instanceof Error ? err.message : String(err));
6204
+ } finally {
6205
+ setBusy(null);
6206
+ }
6207
+ };
6208
+ const handleRefreshCatalog = async () => {
6209
+ try {
6210
+ setBusy("catalog");
6211
+ setError(null);
6212
+ const updated = await fetchApi$5("/catalog/refresh", { method: "POST" });
6213
+ setStatus(updated);
6214
+ setContextDrafts(contextDraftsFor(updated));
6215
+ notifyChange();
6216
+ } catch (err) {
6217
+ setError(err instanceof Error ? err.message : String(err));
6218
+ } finally {
6219
+ setBusy(null);
6220
+ }
6221
+ };
6222
+ const handleTestConnection = async () => {
6223
+ try {
6224
+ setBusy("connection");
6225
+ setError(null);
6226
+ await fetchApi$5("/connection/test", { method: "POST" });
6227
+ await loadStatus(true);
6228
+ } catch (err) {
6229
+ setError(err instanceof Error ? err.message : String(err));
6230
+ } finally {
6231
+ setBusy(null);
6232
+ }
6233
+ };
6234
+ const applyEnabled = async (enabledModelIds) => {
6235
+ try {
6236
+ const updated = await fetchApi$5("/models", {
6237
+ method: "POST",
6238
+ body: JSON.stringify({ enabledModelIds })
6239
+ });
6240
+ setStatus(updated);
6241
+ setContextDrafts(contextDraftsFor(updated));
6242
+ notifyChange();
6243
+ } catch (err) {
6244
+ setError(err instanceof Error ? err.message : String(err));
6245
+ }
6246
+ };
6247
+ const toggleEnabled = async (enabled) => {
6248
+ setStatus((prev) => prev ? {
6249
+ ...prev,
6250
+ enabled
6251
+ } : prev);
6252
+ try {
6253
+ const updated = await fetchApi$5("/settings", {
6254
+ method: "POST",
6255
+ body: JSON.stringify({ enabled })
6256
+ });
6257
+ setStatus(updated);
6258
+ notifyChange();
6259
+ } catch (err) {
6260
+ setError(err instanceof Error ? err.message : String(err));
6261
+ loadStatus(true);
6262
+ }
6263
+ };
6264
+ const toggleModel = (modelId, checked) => {
6265
+ if (!status) return;
6266
+ const current = status.models.filter((model) => model.enabled).map((model) => model.id);
6267
+ const next = checked ? [.../* @__PURE__ */ new Set([...current, modelId])] : current.filter((id) => id !== modelId);
6268
+ applyEnabled(next);
6269
+ };
6270
+ const setAllModels = (selectAll) => {
6271
+ if (!status || status.models.length === 0) return;
6272
+ applyEnabled(selectAll ? status.models.map((model) => model.id) : []);
6273
+ };
6274
+ const handleUpdateEffort = async (effort) => {
6275
+ try {
6276
+ const updated = await fetchApi$5("/settings", {
6277
+ method: "POST",
6278
+ body: JSON.stringify({ defaultReasoningEffort: effort })
6279
+ });
6280
+ setStatus(updated);
6281
+ notifyChange();
6282
+ } catch (err) {
6283
+ setError(err instanceof Error ? err.message : String(err));
6284
+ }
6285
+ };
6286
+ const handleSaveContextWindow = async (modelId) => {
6287
+ const raw = contextDrafts[modelId] || "";
6288
+ const parsed = parsePositiveCapacity(raw);
6289
+ if (parsed === null) {
6290
+ setError(`Invalid context capacity: ${raw}`);
6291
+ return;
6292
+ }
6293
+ try {
6294
+ setSavingModel(modelId);
6295
+ setError(null);
6296
+ const updated = await fetchApi$5("/settings", {
6297
+ method: "POST",
6298
+ body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
6299
+ });
6300
+ setStatus(updated);
6301
+ setContextDrafts((prev) => ({
6302
+ ...prev,
6303
+ [modelId]: formatCapacity(parsed)
6304
+ }));
6305
+ notifyChange();
6306
+ } catch (err) {
6307
+ setError(err instanceof Error ? err.message : String(err));
6308
+ } finally {
6309
+ setSavingModel(null);
6310
+ }
6311
+ };
6312
+ /** Clear one override; the row falls back to the declared window. */
6313
+ const handleResetContextWindow = async (modelId) => {
6314
+ try {
6315
+ setSavingModel(modelId);
6316
+ setError(null);
6317
+ const updated = await fetchApi$5("/settings", {
6318
+ method: "POST",
6319
+ body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
6320
+ });
6321
+ setStatus(updated);
6322
+ setContextDrafts((prev) => {
6323
+ const model = updated.models.find((candidate) => candidate.id === modelId);
6324
+ return model === void 0 ? prev : {
6325
+ ...prev,
6326
+ [modelId]: formatCapacity(model.defaultContextWindow)
6327
+ };
6328
+ });
6329
+ notifyChange();
6330
+ } catch (err) {
6331
+ setError(err instanceof Error ? err.message : String(err));
6332
+ } finally {
6333
+ setSavingModel(null);
6334
+ }
6335
+ };
6336
+ /** Clear every stored override, including models the picker no longer shows. */
6337
+ const handleResetAllContextWindows = async () => {
6338
+ const models = Object.keys(status?.contextWindowOverrides ?? {});
6339
+ if (models.length === 0) return;
6340
+ if (typeof window !== "undefined" && !window.confirm(t.contextWindowResetAllConfirm)) return;
6341
+ try {
6342
+ setBusy("context");
6343
+ setError(null);
6344
+ const updated = await fetchApi$5("/settings", {
6345
+ method: "POST",
6346
+ body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
6347
+ });
6348
+ setStatus(updated);
6349
+ setContextDrafts(contextDraftsFor(updated));
6350
+ notifyChange();
6351
+ } catch (err) {
6352
+ setError(err instanceof Error ? err.message : String(err));
6353
+ } finally {
6354
+ setBusy(null);
6355
+ }
6356
+ };
6357
+ if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6358
+ className: "dsha-page",
6359
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6360
+ className: "dsha-empty",
6361
+ children: t.loading
6362
+ })
6363
+ });
6364
+ const contextModels = status?.models.filter((model) => model.enabled) ?? [];
6365
+ const overrideCount = Object.keys(status?.contextWindowOverrides ?? {}).length;
6366
+ const quota = status?.quota;
6367
+ const account = status?.account;
6368
+ const hasMeters = (quota?.meters.length ?? 0) > 0;
6369
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6370
+ className: "dsha-page",
6371
+ children: [
6372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(AccountPoolSection, {
6373
+ accounts: status?.accounts ?? [],
6374
+ activeAccountId: status?.activeAccountId,
6375
+ rotationStrategy: status?.rotationStrategy ?? "sequential",
6376
+ busy,
6377
+ labels: t,
6378
+ onLogin: () => {
6379
+ document.querySelector(`.dsha-page input[type=password]`)?.focus();
6380
+ },
6381
+ onSetPrimary: (accountId) => void handleAccountAction("set-primary", accountId),
6382
+ onDelete: (accountId) => void handleAccountAction("delete", accountId),
6383
+ onClearCooldown: (accountId) => void handleAccountAction("clear-cooldown", accountId),
6384
+ onSetStrategy: (strategy) => void handleSetStrategy(strategy),
6385
+ storageValue: status?.storagePath || "—",
6386
+ renderDetails: (entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
6387
+ entry.keyHint && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6388
+ t.keyHint,
6389
+ ": ",
6390
+ entry.keyHint
6391
+ ] }),
6392
+ entry.region && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6393
+ t.region,
6394
+ ": ",
6395
+ entry.region === "cn" ? t.regionCn : t.regionIntl
6396
+ ] }),
6397
+ entry.planLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6398
+ t.plan,
6399
+ ": ",
6400
+ entry.planLabel
6401
+ ] })
6402
+ ] }),
6403
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6404
+ className: "dsha-muted",
6405
+ style: { paddingTop: 12 },
6406
+ children: t.addKeyHint
6407
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6408
+ className: "dsha-capacity-control dshzp-keyrow",
6409
+ children: [
6410
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
6411
+ className: "dsha-select",
6412
+ "aria-label": t.region,
6413
+ value: region,
6414
+ onChange: (event) => setRegion(event.currentTarget.value === "cn" ? "cn" : "intl"),
6415
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
6416
+ value: "intl",
6417
+ children: t.regionIntl
6418
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
6419
+ value: "cn",
6420
+ children: t.regionCn
6421
+ })]
6422
+ }),
6423
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6424
+ type: "password",
6425
+ "aria-label": t.addKeySection,
6426
+ placeholder: t.keyPlaceholder,
6427
+ value: apiKey,
6428
+ onChange: (event) => setApiKey(event.currentTarget.value),
6429
+ onKeyDown: (event) => {
6430
+ if (event.key === "Enter" && apiKey.trim() !== "") handleAddKey();
6431
+ }
6432
+ }),
6433
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6434
+ type: "button",
6435
+ className: "dsha-context-save",
6436
+ disabled: busy !== null || apiKey.trim() === "",
6437
+ onClick: () => void handleAddKey(),
6438
+ children: busy === "apikey" ? t.keySaving : t.keySave
6439
+ })
6440
+ ]
6441
+ })]
6442
+ }),
6443
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6444
+ className: "dsha-group",
6445
+ children: [
6446
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6447
+ className: "dsha-grouphead",
6448
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.connection })
6449
+ }),
6450
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6451
+ className: "dsha-row",
6452
+ style: { marginBottom: 12 },
6453
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6454
+ className: "dsha-label",
6455
+ style: { fontWeight: 600 },
6456
+ children: t.enableProvider
6457
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6458
+ type: "checkbox",
6459
+ checked: status?.enabled !== false,
6460
+ disabled: busy !== null,
6461
+ onChange: (e) => void toggleEnabled(e.currentTarget.checked)
6462
+ })]
6463
+ }),
6464
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6465
+ className: "dsha-row",
6466
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6467
+ className: "dsha-label",
6468
+ children: t.provider
6469
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6470
+ className: "dsha-value",
6471
+ children: t.providerValue
6472
+ })]
6473
+ }),
6474
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6475
+ className: "dsha-row",
6476
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6477
+ className: "dsha-label",
6478
+ children: t.connectionState
6479
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6480
+ className: "dsha-value",
6481
+ children: status?.authenticated ? t.connected : t.untested
6482
+ })]
6483
+ }),
6484
+ account && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6485
+ className: "dsha-row",
6486
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6487
+ className: "dsha-label",
6488
+ children: t.account
6489
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6490
+ className: "dsha-value",
6491
+ children: [
6492
+ account.keyHint,
6493
+ " · ",
6494
+ account.region === "cn" ? t.regionCn : t.regionIntl
6495
+ ]
6496
+ })]
6497
+ }),
6498
+ account?.planLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6499
+ className: "dsha-row",
6500
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6501
+ className: "dsha-label",
6502
+ children: t.plan
6503
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6504
+ className: "dsha-value",
6505
+ children: account.planLabel
6506
+ })]
6507
+ }),
6508
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6509
+ className: "dsha-row",
6510
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6511
+ className: "dsha-label",
6512
+ children: t.storage
6513
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6514
+ className: "dsha-value",
6515
+ children: status?.storagePath ?? "—"
6516
+ })]
6517
+ }),
6518
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6519
+ className: "dsha-notice",
6520
+ children: status?.serving === false && status.conflict ? t.routeConflict.replace("{detail}", status.conflict) : t.routeOwned
6521
+ }),
6522
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6523
+ className: "dsha-actions",
6524
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6525
+ className: "dsha-btn",
6526
+ disabled: busy !== null || !status?.authenticated,
6527
+ onClick: () => void handleTestConnection(),
6528
+ children: busy === "connection" ? t.testingConnection : t.testConnection
6529
+ })
6530
+ })
6531
+ ]
6532
+ }),
6533
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6534
+ className: "dsha-group",
6535
+ children: [
6536
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6537
+ className: "dsha-grouphead",
6538
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.modelsSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6539
+ className: "dsha-btn",
6540
+ disabled: busy !== null,
6541
+ onClick: () => void handleRefreshCatalog(),
6542
+ children: busy === "catalog" ? t.refreshingCatalog : t.refreshCatalog
6543
+ })]
6544
+ }),
6545
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6546
+ className: "dsha-muted dsha-models-hint",
6547
+ children: t.modelsHint
6548
+ }),
6549
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6550
+ className: "dsha-models",
6551
+ "aria-label": "GLM Coding Plan Models",
6552
+ children: status?.models.map((model) => {
6553
+ const capabilities = [
6554
+ model.supportsImage ? "image" : null,
6555
+ model.reasoningEfforts.length > 0 ? model.reasoningEfforts.join("/") : null,
6556
+ `${t.effectiveWindow} ${formatCapacity(model.contextWindow)}`
6557
+ ].filter((part) => part !== null).join(" · ");
6558
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
6559
+ title: `${model.id} · ${capabilities}`,
6560
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6561
+ type: "checkbox",
6562
+ checked: model.enabled,
6563
+ disabled: busy !== null,
6564
+ onChange: (event) => toggleModel(model.id, event.currentTarget.checked)
6565
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name })]
6566
+ }, model.id);
6567
+ })
6568
+ }),
6569
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6570
+ className: "dsha-actions",
6571
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6572
+ className: "dsha-btn",
6573
+ disabled: busy !== null,
6574
+ onClick: () => setAllModels(true),
6575
+ children: t.selectAll
6576
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6577
+ className: "dsha-btn",
6578
+ disabled: busy !== null,
6579
+ onClick: () => setAllModels(false),
6580
+ children: t.unselectAll
6581
+ })]
6582
+ })
6583
+ ]
6584
+ }),
6585
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6586
+ className: "dsha-group",
6587
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6588
+ className: "dsha-grouphead",
6589
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.enhanced })
6590
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6591
+ className: "dsha-pref-row",
6592
+ 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", {
6593
+ className: "dsha-muted",
6594
+ children: t.defaultReasoningEffortHint
6595
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
6596
+ className: "dsha-select",
6597
+ "aria-label": t.defaultReasoningEffort,
6598
+ value: status?.defaultReasoningEffort ?? "",
6599
+ disabled: busy !== null,
6600
+ onChange: (event) => {
6601
+ const value = event.currentTarget.value;
6602
+ handleUpdateEffort(value === "" ? null : value);
6603
+ },
6604
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
6605
+ value: "",
6606
+ children: t.defaultEffortAuto
6607
+ }), ZHIPU_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
6608
+ value: effort,
6609
+ children: EFFORT_LABELS[effort]
6610
+ }, effort))]
6611
+ })]
6612
+ })]
6613
+ }),
6614
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6615
+ className: "dsha-group",
6616
+ children: [
6617
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6618
+ className: "dsha-grouphead",
6619
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.contextWindowSection })
6620
+ }),
6621
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6622
+ className: "dsha-muted",
6623
+ children: t.contextWindowHint
6624
+ }),
6625
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5239
6626
  className: "dsha-context-settings",
5240
- children: status?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5241
- className: "dsha-context-row",
5242
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5243
- title: model.id,
5244
- children: model.name
5245
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5246
- className: "dsha-capacity-control",
5247
- children: [
5248
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5249
- type: "text",
5250
- "aria-label": `${model.name} context window`,
5251
- value: contextDrafts[model.id] ?? "",
5252
- onChange: (event) => setContextDrafts({
5253
- ...contextDrafts,
5254
- [model.id]: event.currentTarget.value
6627
+ children: [
6628
+ contextModels.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6629
+ className: "dsha-muted",
6630
+ children: t.contextWindowNoneEnabled
6631
+ }),
6632
+ contextModels.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6633
+ className: "dsha-context-row",
6634
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6635
+ title: model.id,
6636
+ children: model.name
6637
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6638
+ className: "dsha-capacity-control",
6639
+ children: [
6640
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6641
+ type: "text",
6642
+ "aria-label": `${model.name} context window`,
6643
+ value: contextDrafts[model.id] ?? "",
6644
+ onChange: (event) => setContextDrafts({
6645
+ ...contextDrafts,
6646
+ [model.id]: event.currentTarget.value
6647
+ }),
6648
+ onKeyDown: (event) => {
6649
+ if (event.key === "Enter") handleSaveContextWindow(model.id);
6650
+ }
5255
6651
  }),
5256
- onKeyDown: (event) => {
5257
- if (event.key === "Enter") handleSaveContextWindow(model.id);
5258
- }
5259
- }),
5260
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "tokens" }),
5261
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5262
- type: "button",
5263
- className: "dsha-context-save",
5264
- disabled: savingModel === model.id,
5265
- onClick: () => void handleSaveContextWindow(model.id),
5266
- children: savingModel === model.id ? t.saving : t.save
5267
- })
5268
- ]
5269
- })]
5270
- }, model.id))
6652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
6653
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6654
+ type: "button",
6655
+ className: "dsha-context-save",
6656
+ disabled: savingModel === model.id,
6657
+ onClick: () => void handleSaveContextWindow(model.id),
6658
+ children: savingModel === model.id ? t.saving : t.save
6659
+ }),
6660
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6661
+ type: "button",
6662
+ className: "dsha-context-save dsha-context-reset",
6663
+ "aria-label": `${model.name} ${t.contextWindowReset}`,
6664
+ disabled: savingModel === model.id || status?.contextWindowOverrides[model.id] === void 0,
6665
+ onClick: () => void handleResetContextWindow(model.id),
6666
+ children: t.contextWindowReset
6667
+ })
6668
+ ]
6669
+ })]
6670
+ }, model.id)),
6671
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6672
+ className: "dsha-actions",
6673
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6674
+ className: "dsha-btn",
6675
+ disabled: busy !== null || overrideCount === 0,
6676
+ onClick: () => void handleResetAllContextWindows(),
6677
+ children: t.contextWindowResetAll
6678
+ })
6679
+ })
6680
+ ]
5271
6681
  })
5272
6682
  ]
5273
6683
  }),
@@ -5278,7 +6688,7 @@ window.__ModuleLoader__.load({
5278
6688
  className: "dsha-grouphead",
5279
6689
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5280
6690
  className: "dsha-btn",
5281
- disabled: busy !== null || !authenticated,
6691
+ disabled: busy !== null || !status?.authenticated,
5282
6692
  onClick: () => void handleRefreshQuota(),
5283
6693
  children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
5284
6694
  })]
@@ -5287,81 +6697,100 @@ window.__ModuleLoader__.load({
5287
6697
  className: "dsha-muted",
5288
6698
  children: t.quotaDesc
5289
6699
  }),
5290
- !authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6700
+ !status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5291
6701
  className: "dsha-empty",
5292
6702
  children: t.signedOut
5293
6703
  }) : quota === null || quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5294
6704
  className: "dsha-empty",
5295
- children: busy === "quota" ? t.refreshingQuota : t.quotaEmpty
6705
+ children: busy === "quota" ? t.refreshingQuota : status.quotaError ?? t.quotaEmpty
5296
6706
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5297
6707
  className: "dsha-quota-card",
5298
6708
  children: [
5299
6709
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5300
6710
  className: "dsha-quota-title",
5301
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota.packageName || t.quotaPackage }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.remainingCredits !== null ? `${quota.remainingCredits} ${t.credits}` : "—" })]
6711
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota.planName ?? t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.planLevel ?? t.planUnknown })]
5302
6712
  }),
5303
- quota.cycleUsedCredits !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5304
- className: "dsha-row",
5305
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5306
- className: "dsha-label",
5307
- children: t.quotaCycle
5308
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5309
- className: "dsha-value",
6713
+ quota.renewsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6714
+ className: "dsha-meter-meta",
6715
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6716
+ t.renews,
6717
+ ": ",
6718
+ formatDate(quota.renewsAt)
6719
+ ] })
6720
+ }),
6721
+ quota.windows.map((window) => {
6722
+ const percent = window.remainingFraction === null ? null : Math.round(window.remainingFraction * 100);
6723
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6724
+ className: "dsha-meter-wrap",
5310
6725
  children: [
5311
- quota.cycleUsedCredits,
5312
- quota.cycleCredits !== null ? ` / ${quota.cycleCredits}` : "",
5313
- ` ${t.credits}`
6726
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6727
+ className: "dsha-meter-label",
6728
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: percent === null ? "—" : `${percent}% ${t.left}` })]
6729
+ }),
6730
+ percent !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6731
+ className: "dsha-meter dsha-meter-green",
6732
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${Math.max(0, percent)}%` } })
6733
+ }),
6734
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6735
+ className: "dsha-meter-meta",
6736
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6737
+ window.used ?? "—",
6738
+ " / ",
6739
+ window.limit ?? "—"
6740
+ ] }), window.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6741
+ t.resetAt,
6742
+ ": ",
6743
+ formatReset(window.resetsAt, t.now)
6744
+ ] })]
6745
+ })
5314
6746
  ]
5315
- })]
5316
- }),
5317
- quota.cycleEndsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5318
- className: "dsha-row",
5319
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5320
- className: "dsha-label",
5321
- children: t.quotaReset
5322
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5323
- className: "dsha-value",
5324
- children: [formatDate(quota.cycleEndsAt), formatReset(quota.cycleEndsAt) ? ` · ${formatReset(quota.cycleEndsAt)}` : ""]
5325
- })]
6747
+ }, window.id);
5326
6748
  }),
5327
- quota.meters.map((meter) => {
5328
- const remaining = meter.remainingFraction;
5329
- const percent = remaining === null ? null : Math.round(remaining * 100);
6749
+ quota.meters.filter((meter) => !quota.windows.some((window) => window.id === meter.id)).map((meter) => {
6750
+ const percent = meter.remainingFraction === null ? null : Math.round(meter.remainingFraction * 100);
5330
6751
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5331
6752
  className: "dsha-meter-wrap",
5332
6753
  children: [
5333
6754
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5334
6755
  className: "dsha-meter-label",
5335
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meter.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: percent === null ? meter.limit ?? "—" : `${percent}% left` })]
6756
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meter.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: percent === null ? "—" : `${percent}% ${t.left}` })]
5336
6757
  }),
5337
6758
  percent !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5338
- className: "dsha-meter dsha-meter-green",
5339
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${percent}%` } })
6759
+ className: "dsha-meter dsha-meter-cyan",
6760
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${Math.max(0, percent)}%` } })
5340
6761
  }),
5341
6762
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5342
6763
  className: "dsha-meter-meta",
5343
- children: [meter.used !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5344
- meter.used,
6764
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6765
+ meter.used ?? "—",
5345
6766
  " / ",
5346
6767
  meter.limit ?? "—"
5347
6768
  ] }), meter.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5348
- t.quotaReset,
6769
+ t.resetAt,
5349
6770
  ": ",
5350
- formatReset(meter.resetsAt)
6771
+ formatReset(meter.resetsAt, t.now)
5351
6772
  ] })]
5352
6773
  })
5353
6774
  ]
5354
6775
  }, meter.id);
5355
6776
  }),
5356
- quota.meters.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6777
+ !hasMeters && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5357
6778
  className: "dsha-empty",
5358
- children: t.quotaEmpty
6779
+ children: t.quotaUnavailable
5359
6780
  }),
5360
6781
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5361
6782
  className: "dsha-timestamp",
5362
6783
  children: t.updatedAt.replace("{time}", new Date(quota.fetchedAt).toLocaleString())
5363
6784
  })
5364
6785
  ]
6786
+ }),
6787
+ status?.quotaError && quota !== null && quota !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
6788
+ className: "dsha-muted",
6789
+ children: [
6790
+ t.quotaError,
6791
+ ": ",
6792
+ status.quotaError
6793
+ ]
5365
6794
  })
5366
6795
  ]
5367
6796
  }),
@@ -5394,6 +6823,10 @@ window.__ModuleLoader__.load({
5394
6823
  {
5395
6824
  id: "workbuddy",
5396
6825
  label: "WorkBuddy"
6826
+ },
6827
+ {
6828
+ id: "zhipu",
6829
+ label: "GLM"
5397
6830
  }
5398
6831
  ];
5399
6832
  /**
@@ -5452,7 +6885,8 @@ window.__ModuleLoader__.load({
5452
6885
  active === "antigravity" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AntigravitySection, { onModelChange }) : null,
5453
6886
  active === "command-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CommandCodeSection, { onModelChange }) : null,
5454
6887
  active === "kimi-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KimiCodeSection, { onModelChange }) : null,
5455
- active === "workbuddy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkBuddySection, { onModelChange }) : null
6888
+ active === "workbuddy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkBuddySection, { onModelChange }) : null,
6889
+ active === "zhipu" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZhipuSection, { onModelChange }) : null
5456
6890
  ]
5457
6891
  })
5458
6892
  ]
@@ -5540,9 +6974,13 @@ window.__ModuleLoader__.load({
5540
6974
  searchProviderCodex: "ChatGPT(代理隧道)",
5541
6975
  providerDefault: "使用 Provider 默认值",
5542
6976
  contextWindows: "模型上下文窗口",
5543
- contextWindowsHint: "GPT-6 系列默认 384K(最高 872K),GPT-5.6 系列默认 272K(最高 1M)。该值用于 DSH 的压缩与溢出判断,可输入 872K、512K 等容量。",
6977
+ contextWindowsHint: "只列出已勾选「可用模型」的条目。默认取模型目录值(GPT-6 系列 384K,最高 872K;其余最高 1M),该值用于 DSH 的压缩与溢出判断,可输入 872K、512K 等容量;改过的模型可单独或一键恢复默认。",
5544
6978
  contextWindow: "上下文窗口",
5545
- contextWindowInvalid: "上下文窗口必须是正整数,且不能超过模型上限(GPT-6 系列为 872K,GPT-5.6 系列为 1M);可使用 K 或 M 后缀。",
6979
+ contextWindowInvalid: "上下文窗口必须是正整数,且不能超过模型上限(GPT-6 系列为 872K,其余为 1M);可使用 K 或 M 后缀。",
6980
+ contextWindowReset: "恢复默认",
6981
+ contextWindowResetAll: "全部恢复默认",
6982
+ contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
6983
+ contextWindowsNoneEnabled: "还没有勾选任何模型。在上方「可用模型」里勾选后,这里会出现该模型的上下文窗口设置。",
5546
6984
  saveContextWindow: "保存上下文窗口",
5547
6985
  save: "保存",
5548
6986
  tokens: "tokens",
@@ -5669,9 +7107,13 @@ window.__ModuleLoader__.load({
5669
7107
  searchProviderCodex: "ChatGPT (Proxy tunnel)",
5670
7108
  providerDefault: "Use provider default",
5671
7109
  contextWindows: "Model context windows",
5672
- contextWindowsHint: "GPT-6 defaults to 384K (up to 872K); GPT-5.6 defaults to 272K (up to 1M). DSH uses it for compaction and overflow detection; values such as 872K and 512K are accepted.",
7110
+ contextWindowsHint: "Lists the models checked under Available models. Each starts at its catalog value (384K for the GPT-6 family, up to 872K; up to 1M otherwise); DSH uses it for compaction and overflow detection. Values such as 872K and 512K are accepted, and a changed model can be restored one by one or all at once.",
5673
7111
  contextWindow: "Context window",
5674
- contextWindowInvalid: "The context window must be a positive integer within the model limit (872K for the GPT-6 family, 1M for GPT-5.6). K and M suffixes are accepted.",
7112
+ contextWindowInvalid: "The context window must be a positive integer within the model limit (872K for the GPT-6 family, 1M otherwise). K and M suffixes are accepted.",
7113
+ contextWindowReset: "Restore default",
7114
+ contextWindowResetAll: "Restore all defaults",
7115
+ contextWindowResetAllConfirm: "Restore every changed model context window to its default?",
7116
+ contextWindowsNoneEnabled: "No model is checked yet. Check one under Available models above and its context window setting appears here.",
5675
7117
  saveContextWindow: "Save context window",
5676
7118
  save: "Save",
5677
7119
  tokens: "tokens",
@@ -5723,7 +7165,7 @@ window.__ModuleLoader__.load({
5723
7165
  };
5724
7166
  //#endregion
5725
7167
  //#region src/client/styles.ts
5726
- const STYLE_ID$3 = "@eddyskywalker/dsh-chatgpt-subscription/main";
7168
+ const STYLE_ID$4 = "@eddyskywalker/dsh-chatgpt-subscription/main";
5727
7169
  const CSS = `
5728
7170
  .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}
5729
7171
  .dsh-codex-page *{box-sizing:border-box}
@@ -5832,21 +7274,21 @@ window.__ModuleLoader__.load({
5832
7274
  @media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}
5833
7275
  `;
5834
7276
  function installStyles() {
5835
- if (document.querySelector(`style[data-plugin-css="${STYLE_ID$3}"]`) !== null) return () => void 0;
7277
+ if (document.querySelector(`style[data-plugin-css="${STYLE_ID$4}"]`) !== null) return () => void 0;
5836
7278
  const element = document.createElement("style");
5837
7279
  element.dataset.plugin = "@eddyskywalker/dsh-chatgpt-subscription";
5838
- element.dataset.pluginCss = STYLE_ID$3;
7280
+ element.dataset.pluginCss = STYLE_ID$4;
5839
7281
  element.textContent = CSS;
5840
7282
  document.head.appendChild(element);
5841
7283
  return () => element.remove();
5842
7284
  }
5843
7285
  //#endregion
5844
7286
  //#region src/client/antigravity/styles.ts
5845
- const STYLE_ID$2 = "dsh-antigravity-settings-style";
7287
+ const STYLE_ID$3 = "dsh-antigravity-settings-style";
5846
7288
  function installAntigravityStyles() {
5847
7289
  if (typeof document === "undefined" || document.getElementById("dsh-antigravity-settings-style")) return;
5848
7290
  const style = document.createElement("style");
5849
- style.id = STYLE_ID$2;
7291
+ style.id = STYLE_ID$3;
5850
7292
  style.textContent = `
5851
7293
  .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}
5852
7294
  .dsha-page *{box-sizing:border-box}
@@ -5884,6 +7326,8 @@ window.__ModuleLoader__.load({
5884
7326
  .dsha-context-save{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:12px;line-height:1;padding:8px 10px;white-space:nowrap}
5885
7327
  .dsha-context-save:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
5886
7328
  .dsha-context-save:disabled{cursor:default;opacity:.45}
7329
+ .dsha-context-reset{color:var(--dsw-alias-label-secondary)}
7330
+ .dsha-context-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
5887
7331
  .dsha-quota-card{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:8px;margin-top:12px;padding:12px}
5888
7332
  .dsha-quota-title{align-items:center;display:flex;font-size:13px;gap:8px;justify-content:space-between;color:var(--dsw-alias-label-primary);font-weight:650}
5889
7333
  .dsha-quota-title span{color:var(--dsw-alias-label-tertiary);font-size:11px;text-transform:uppercase}
@@ -5945,9 +7389,9 @@ window.__ModuleLoader__.load({
5945
7389
  }
5946
7390
  //#endregion
5947
7391
  //#region src/client/antigravity/AntigravityComposerQuota.tsx
5948
- const API$3 = "/antigravity/api";
5949
- async function fetchApi$3(path, options) {
5950
- const res = await fetch(`${API$3}${path}`, {
7392
+ const API$4 = "/antigravity/api";
7393
+ async function fetchApi$4(path, options) {
7394
+ const res = await fetch(`${API$4}${path}`, {
5951
7395
  ...options,
5952
7396
  headers: {
5953
7397
  "Content-Type": "application/json",
@@ -5988,7 +7432,7 @@ window.__ModuleLoader__.load({
5988
7432
  }
5989
7433
  }
5990
7434
  function AntigravityComposerQuota({ directory, loadModelDirectory }) {
5991
- const modelState = useStore$3(directory);
7435
+ const modelState = useStore$4(directory);
5992
7436
  const [status, setStatus] = (0, react.useState)(null);
5993
7437
  const [loading, setLoading] = (0, react.useState)(false);
5994
7438
  const mountedRef = (0, react.useRef)(false);
@@ -6007,7 +7451,7 @@ window.__ModuleLoader__.load({
6007
7451
  if (!mountedRef.current) return;
6008
7452
  setLoading(true);
6009
7453
  try {
6010
- const data = refresh ? await fetchApi$3("/quota", { method: "POST" }) : await fetchApi$3("/status");
7454
+ const data = refresh ? await fetchApi$4("/quota", { method: "POST" }) : await fetchApi$4("/status");
6011
7455
  if (mountedRef.current) setStatus(data);
6012
7456
  } catch {} finally {
6013
7457
  if (mountedRef.current) setLoading(false);
@@ -6045,14 +7489,14 @@ window.__ModuleLoader__.load({
6045
7489
  })]
6046
7490
  });
6047
7491
  }
6048
- function useStore$3(store) {
7492
+ function useStore$4(store) {
6049
7493
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
6050
7494
  }
6051
7495
  //#endregion
6052
7496
  //#region src/client/command-code/CommandCodeComposerQuota.tsx
6053
- const API$2 = "/command-code/api";
6054
- async function fetchApi$2(path, options) {
6055
- const res = await fetch(`${API$2}${path}`, {
7497
+ const API$3 = "/command-code/api";
7498
+ async function fetchApi$3(path, options) {
7499
+ const res = await fetch(`${API$3}${path}`, {
6056
7500
  ...options,
6057
7501
  headers: {
6058
7502
  "Content-Type": "application/json",
@@ -6069,7 +7513,7 @@ window.__ModuleLoader__.load({
6069
7513
  * A bounded usage window is the number a user actually spends down, so it wins
6070
7514
  * over a credit balance; the balance shows only when no window is reported.
6071
7515
  */
6072
- function selectBadgeFacts$2(status) {
7516
+ function selectBadgeFacts$3(status) {
6073
7517
  const quota = status?.quota;
6074
7518
  if (quota === null || quota === void 0) return {
6075
7519
  text: "—",
@@ -6111,7 +7555,7 @@ window.__ModuleLoader__.load({
6111
7555
  };
6112
7556
  }
6113
7557
  function CommandCodeComposerQuota({ directory, loadModelDirectory }) {
6114
- const modelState = useStore$2(directory);
7558
+ const modelState = useStore$3(directory);
6115
7559
  const [status, setStatus] = (0, react.useState)(null);
6116
7560
  const [loading, setLoading] = (0, react.useState)(false);
6117
7561
  const mountedRef = (0, react.useRef)(false);
@@ -6129,7 +7573,7 @@ window.__ModuleLoader__.load({
6129
7573
  if (!mountedRef.current) return;
6130
7574
  setLoading(true);
6131
7575
  try {
6132
- const data = refresh ? await fetchApi$2("/quota", { method: "POST" }) : await fetchApi$2("/status");
7576
+ const data = refresh ? await fetchApi$3("/quota", { method: "POST" }) : await fetchApi$3("/status");
6133
7577
  if (mountedRef.current) setStatus(data);
6134
7578
  } catch {} finally {
6135
7579
  if (mountedRef.current) setLoading(false);
@@ -6145,7 +7589,7 @@ window.__ModuleLoader__.load({
6145
7589
  window.clearInterval(timer);
6146
7590
  };
6147
7591
  }, [fetchStatus, isCommandCode]);
6148
- const facts = (0, react.useMemo)(() => selectBadgeFacts$2(status), [status]);
7592
+ const facts = (0, react.useMemo)(() => selectBadgeFacts$3(status), [status]);
6149
7593
  if (!isCommandCode || !status?.authenticated || facts === null) return null;
6150
7594
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6151
7595
  className: "dsha-composer-quota",
@@ -6162,14 +7606,14 @@ window.__ModuleLoader__.load({
6162
7606
  })]
6163
7607
  });
6164
7608
  }
6165
- function useStore$2(store) {
7609
+ function useStore$3(store) {
6166
7610
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
6167
7611
  }
6168
7612
  //#endregion
6169
7613
  //#region src/client/kimi-code/KimiCodeComposerQuota.tsx
6170
- const API$1 = "/kimi-code/api";
6171
- async function fetchApi$1(path, options) {
6172
- const res = await fetch(`${API$1}${path}`, {
7614
+ const API$2 = "/kimi-code/api";
7615
+ async function fetchApi$2(path, options) {
7616
+ const res = await fetch(`${API$2}${path}`, {
6173
7617
  ...options,
6174
7618
  headers: {
6175
7619
  "Content-Type": "application/json",
@@ -6187,7 +7631,7 @@ window.__ModuleLoader__.load({
6187
7631
  * blocks work soonest, so it wins over the longer pools; the 7-day allowance
6188
7632
  * shows only when no 5-hour window is reported.
6189
7633
  */
6190
- function selectBadgeFacts$1(status) {
7634
+ function selectBadgeFacts$2(status) {
6191
7635
  const quota = status?.quota;
6192
7636
  if (quota === null || quota === void 0) return {
6193
7637
  text: "—",
@@ -6219,7 +7663,7 @@ window.__ModuleLoader__.load({
6219
7663
  };
6220
7664
  }
6221
7665
  function KimiCodeComposerQuota({ directory, loadModelDirectory }) {
6222
- const modelState = useStore$1(directory);
7666
+ const modelState = useStore$2(directory);
6223
7667
  const [status, setStatus] = (0, react.useState)(null);
6224
7668
  const [loading, setLoading] = (0, react.useState)(false);
6225
7669
  const mountedRef = (0, react.useRef)(false);
@@ -6237,7 +7681,7 @@ window.__ModuleLoader__.load({
6237
7681
  if (!mountedRef.current) return;
6238
7682
  setLoading(true);
6239
7683
  try {
6240
- const data = refresh ? await fetchApi$1("/quota", { method: "POST" }) : await fetchApi$1("/status");
7684
+ const data = refresh ? await fetchApi$2("/quota", { method: "POST" }) : await fetchApi$2("/status");
6241
7685
  if (mountedRef.current) setStatus(data);
6242
7686
  } catch {} finally {
6243
7687
  if (mountedRef.current) setLoading(false);
@@ -6253,7 +7697,7 @@ window.__ModuleLoader__.load({
6253
7697
  window.clearInterval(timer);
6254
7698
  };
6255
7699
  }, [fetchStatus, isKimiCode]);
6256
- const facts = (0, react.useMemo)(() => selectBadgeFacts$1(status), [status]);
7700
+ const facts = (0, react.useMemo)(() => selectBadgeFacts$2(status), [status]);
6257
7701
  if (!isKimiCode || !status?.authenticated || facts === null) return null;
6258
7702
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6259
7703
  className: "dsha-composer-quota",
@@ -6270,12 +7714,12 @@ window.__ModuleLoader__.load({
6270
7714
  })]
6271
7715
  });
6272
7716
  }
6273
- function useStore$1(store) {
7717
+ function useStore$2(store) {
6274
7718
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
6275
7719
  }
6276
7720
  //#endregion
6277
7721
  //#region src/client/kimi-code/styles.ts
6278
- const STYLE_ID$1 = "dsh-kimi-code-settings-style";
7722
+ const STYLE_ID$2 = "dsh-kimi-code-settings-style";
6279
7723
  /**
6280
7724
  * Node the base control styles come from.
6281
7725
  *
@@ -6320,6 +7764,8 @@ window.__ModuleLoader__.load({
6320
7764
  .dsha-context-save{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:12px;line-height:1;padding:8px 10px;white-space:nowrap}
6321
7765
  .dsha-context-save:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
6322
7766
  .dsha-context-save:disabled{cursor:default;opacity:.45}
7767
+ .dsha-context-reset{color:var(--dsw-alias-label-secondary)}
7768
+ .dsha-context-reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
6323
7769
  .dsha-quota-card{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:8px;margin-top:12px;padding:12px}
6324
7770
  .dsha-quota-title{align-items:center;display:flex;font-size:13px;gap:8px;justify-content:space-between;color:var(--dsw-alias-label-primary);font-weight:650}
6325
7771
  .dsha-quota-title span{color:var(--dsw-alias-label-tertiary);font-size:11px;text-transform:uppercase}
@@ -6365,15 +7811,15 @@ window.__ModuleLoader__.load({
6365
7811
  function installKimiCodeStyles() {
6366
7812
  if (typeof document === "undefined" || document.getElementById("dsh-kimi-code-settings-style")) return;
6367
7813
  const style = document.createElement("style");
6368
- style.id = STYLE_ID$1;
7814
+ style.id = STYLE_ID$2;
6369
7815
  style.textContent = BASE;
6370
7816
  document.head.appendChild(style);
6371
7817
  }
6372
7818
  //#endregion
6373
7819
  //#region src/client/workbuddy/WorkBuddyComposerQuota.tsx
6374
- const API = "/workbuddy/api";
6375
- async function fetchApi(path, options) {
6376
- const res = await fetch(`${API}${path}`, {
7820
+ const API$1 = "/workbuddy/api";
7821
+ async function fetchApi$1(path, options) {
7822
+ const res = await fetch(`${API$1}${path}`, {
6377
7823
  ...options,
6378
7824
  headers: {
6379
7825
  "Content-Type": "application/json",
@@ -6392,7 +7838,7 @@ window.__ModuleLoader__.load({
6392
7838
  * payload reports both a cycle meter and a package meter, and the cycle meter
6393
7839
  * is the one that actually resets, so it is preferred when both exist.
6394
7840
  */
6395
- function selectBadgeFacts(status) {
7841
+ function selectBadgeFacts$1(status) {
6396
7842
  const quota = status?.quota;
6397
7843
  if (quota === null || quota === void 0) return {
6398
7844
  text: "—",
@@ -6420,7 +7866,7 @@ window.__ModuleLoader__.load({
6420
7866
  };
6421
7867
  }
6422
7868
  function WorkBuddyComposerQuota({ directory, loadModelDirectory }) {
6423
- const modelState = useStore(directory);
7869
+ const modelState = useStore$1(directory);
6424
7870
  const [status, setStatus] = (0, react.useState)(null);
6425
7871
  const [loading, setLoading] = (0, react.useState)(false);
6426
7872
  const mountedRef = (0, react.useRef)(false);
@@ -6438,7 +7884,7 @@ window.__ModuleLoader__.load({
6438
7884
  if (!mountedRef.current) return;
6439
7885
  setLoading(true);
6440
7886
  try {
6441
- const data = refresh ? await fetchApi("/quota", { method: "POST" }) : await fetchApi("/status");
7887
+ const data = refresh ? await fetchApi$1("/quota", { method: "POST" }) : await fetchApi$1("/status");
6442
7888
  if (mountedRef.current) setStatus(data);
6443
7889
  } catch {} finally {
6444
7890
  if (mountedRef.current) setLoading(false);
@@ -6454,7 +7900,7 @@ window.__ModuleLoader__.load({
6454
7900
  window.clearInterval(timer);
6455
7901
  };
6456
7902
  }, [fetchStatus, isWorkBuddy]);
6457
- const facts = (0, react.useMemo)(() => selectBadgeFacts(status), [status]);
7903
+ const facts = (0, react.useMemo)(() => selectBadgeFacts$1(status), [status]);
6458
7904
  if (!isWorkBuddy || !status?.authenticated || facts === null) return null;
6459
7905
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6460
7906
  className: "dsha-composer-quota",
@@ -6471,12 +7917,12 @@ window.__ModuleLoader__.load({
6471
7917
  })]
6472
7918
  });
6473
7919
  }
6474
- function useStore(store) {
7920
+ function useStore$1(store) {
6475
7921
  return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
6476
7922
  }
6477
7923
  //#endregion
6478
7924
  //#region src/client/workbuddy/styles.ts
6479
- const STYLE_ID = "dsh-workbuddy-settings-style";
7925
+ const STYLE_ID$1 = "dsh-workbuddy-settings-style";
6480
7926
  /**
6481
7927
  * WorkBuddy-only additions to the shared settings design system.
6482
7928
  *
@@ -6492,12 +7938,141 @@ window.__ModuleLoader__.load({
6492
7938
  function installWorkBuddyStyles() {
6493
7939
  if (typeof document === "undefined" || document.getElementById("dsh-workbuddy-settings-style")) return;
6494
7940
  const style = document.createElement("style");
6495
- style.id = STYLE_ID;
7941
+ style.id = STYLE_ID$1;
6496
7942
  style.textContent = `
6497
7943
  .dshwb-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px}
6498
7944
  .dsha-account-add-actions{display:flex;flex-wrap:wrap;gap:8px}
6499
7945
  .dsha-account-add-actions .dsha-btn{background:var(--dsw-alias-button-info-fill,#397ee8);border-color:transparent;color:var(--dsw-alias-button-info-label,#fff)}
6500
7946
  .dsha-account-add-actions .dsha-btn:hover:not(:disabled){opacity:.9;background:var(--dsw-alias-button-info-fill,#397ee8)}
7947
+ `;
7948
+ document.head.append(style);
7949
+ }
7950
+ //#endregion
7951
+ //#region src/client/zhipu/ZhipuComposerQuota.tsx
7952
+ const API = "/zhipu/api";
7953
+ async function fetchApi(path, options) {
7954
+ const res = await fetch(`${API}${path}`, {
7955
+ ...options,
7956
+ headers: {
7957
+ "Content-Type": "application/json",
7958
+ ...options?.headers
7959
+ }
7960
+ });
7961
+ const json = await res.json();
7962
+ if (!res.ok || !json.ok) throw new Error(json.error || `HTTP ${res.status}`);
7963
+ return json.value;
7964
+ }
7965
+ /**
7966
+ * Pick the most meaningful number for the badge.
7967
+ *
7968
+ * A Coding Plan is bounded by two windows at once, and the one closer to
7969
+ * exhaustion is what the user needs to see: the 5-hour window can be spent
7970
+ * while the weekly one has room, and the reverse. So the tightest *remaining*
7971
+ * fraction wins, and its window names the tooltip.
7972
+ */
7973
+ function selectBadgeFacts(status) {
7974
+ const quota = status?.quota;
7975
+ if (quota === null || quota === void 0) return {
7976
+ text: "—",
7977
+ tooltip: "GLM Coding Plan quota unavailable — click to refresh",
7978
+ level: "normal"
7979
+ };
7980
+ let tightest = null;
7981
+ for (const window of quota.windows) {
7982
+ if (window.remainingFraction === null) continue;
7983
+ if (tightest === null || window.remainingFraction < tightest.remaining) tightest = {
7984
+ label: window.label,
7985
+ remaining: window.remainingFraction
7986
+ };
7987
+ }
7988
+ if (tightest === null) return {
7989
+ text: "—",
7990
+ tooltip: "GLM Coding Plan quota unavailable — click to refresh",
7991
+ level: "normal"
7992
+ };
7993
+ const remaining = Math.round(tightest.remaining * 100);
7994
+ return {
7995
+ text: `${remaining}%`,
7996
+ tooltip: `[GLM Coding Plan] ${tightest.label}: ${remaining}% left`,
7997
+ level: remaining <= 5 ? "danger" : remaining <= 20 ? "warning" : "normal"
7998
+ };
7999
+ }
8000
+ function ZhipuComposerQuota({ directory, loadModelDirectory }) {
8001
+ const modelState = useStore(directory);
8002
+ const [status, setStatus] = (0, react.useState)(null);
8003
+ const [loading, setLoading] = (0, react.useState)(false);
8004
+ const mountedRef = (0, react.useRef)(false);
8005
+ const isZhipu = modelState.current?.provider === "zhipu-coding-plan";
8006
+ (0, react.useEffect)(() => {
8007
+ loadModelDirectory();
8008
+ }, [loadModelDirectory]);
8009
+ (0, react.useEffect)(() => {
8010
+ mountedRef.current = true;
8011
+ return () => {
8012
+ mountedRef.current = false;
8013
+ };
8014
+ }, []);
8015
+ const fetchStatus = (0, react.useCallback)(async (refresh = false) => {
8016
+ if (!mountedRef.current) return;
8017
+ setLoading(true);
8018
+ try {
8019
+ const data = refresh ? await fetchApi("/quota", { method: "POST" }) : await fetchApi("/status");
8020
+ if (mountedRef.current) setStatus(data);
8021
+ } catch {} finally {
8022
+ if (mountedRef.current) setLoading(false);
8023
+ }
8024
+ }, []);
8025
+ (0, react.useEffect)(() => {
8026
+ if (!isZhipu) return;
8027
+ fetchStatus(false);
8028
+ const timer = window.setInterval(() => {
8029
+ if (document.visibilityState === "visible") fetchStatus(false);
8030
+ }, 6e4);
8031
+ return () => {
8032
+ window.clearInterval(timer);
8033
+ };
8034
+ }, [fetchStatus, isZhipu]);
8035
+ const facts = (0, react.useMemo)(() => selectBadgeFacts(status), [status]);
8036
+ if (!isZhipu || !status?.authenticated || facts === null) return null;
8037
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8038
+ className: "dsha-composer-quota",
8039
+ "data-level": facts.level,
8040
+ title: facts.tooltip,
8041
+ "aria-label": facts.tooltip,
8042
+ onClick: () => void fetchStatus(true),
8043
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8044
+ className: "dsha-composer-quota-label",
8045
+ children: "额度"
8046
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
8047
+ className: "dsha-composer-quota-val",
8048
+ children: loading ? "…" : facts.text
8049
+ })]
8050
+ });
8051
+ }
8052
+ function useStore(store) {
8053
+ return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
8054
+ }
8055
+ //#endregion
8056
+ //#region src/client/zhipu/styles.ts
8057
+ const STYLE_ID = "dsh-zhipu-settings-style";
8058
+ /**
8059
+ * GLM Coding Plan additions to the shared settings design system.
8060
+ *
8061
+ * The base control styles (`.dsha-page`, `.dsha-group`, `.dsha-models`, the
8062
+ * account card, the meters, …) come from the stylesheets the sibling routes
8063
+ * install, in the same order the client installs them, so this file declares
8064
+ * only what stays unique to this card: the key-hint line and the region
8065
+ * selector that sits beside the key input.
8066
+ */
8067
+ function installZhipuStyles() {
8068
+ if (typeof document === "undefined" || document.getElementById("dsh-zhipu-settings-style")) return;
8069
+ const style = document.createElement("style");
8070
+ style.id = STYLE_ID;
8071
+ style.textContent = `
8072
+ .dshzp-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px}
8073
+ .dshzp-keyrow{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
8074
+ .dshzp-keyrow .dsha-select{min-width:190px}
8075
+ .dshzp-keyrow input[type=password]{flex:1 1 260px;min-width:200px}
6501
8076
  `;
6502
8077
  document.head.append(style);
6503
8078
  }
@@ -6844,22 +8419,27 @@ window.__ModuleLoader__.load({
6844
8419
  function apply(ctx) {
6845
8420
  ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-chatgpt-subscription: dictionaries");
6846
8421
  ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
6847
- ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$4), "dsh-antigravity: dictionaries");
8422
+ ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$5), "dsh-antigravity: dictionaries");
6848
8423
  ctx.effect(() => {
6849
8424
  installAntigravityStyles();
6850
8425
  return () => {};
6851
8426
  }, "dsh-antigravity: styles");
6852
- ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$3), "dsh-command-code: dictionaries");
6853
- ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$2), "dsh-kimi-code: dictionaries");
8427
+ ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$4), "dsh-command-code: dictionaries");
8428
+ ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$3), "dsh-kimi-code: dictionaries");
6854
8429
  ctx.effect(() => {
6855
8430
  installKimiCodeStyles();
6856
8431
  return () => {};
6857
8432
  }, "dsh-kimi-code: styles");
6858
- ctx.effect(() => ctx.locale.register(NS_WORKBUDDY, dictionaries$1), "dsh-workbuddy: dictionaries");
8433
+ ctx.effect(() => ctx.locale.register(NS_WORKBUDDY, dictionaries$2), "dsh-workbuddy: dictionaries");
6859
8434
  ctx.effect(() => {
6860
8435
  installWorkBuddyStyles();
6861
8436
  return () => {};
6862
8437
  }, "dsh-workbuddy: styles");
8438
+ ctx.effect(() => ctx.locale.register(NS_ZHIPU, dictionaries$1), "dsh-zhipu: dictionaries");
8439
+ ctx.effect(() => {
8440
+ installZhipuStyles();
8441
+ return () => {};
8442
+ }, "dsh-zhipu: styles");
6863
8443
  ctx.effect(() => {
6864
8444
  installPoolStyles();
6865
8445
  return () => {};
@@ -6962,6 +8542,21 @@ window.__ModuleLoader__.load({
6962
8542
  };
6963
8543
  }
6964
8544
  }, WorkBuddyComposerQuota));
8545
+ ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
8546
+ name: "conversation.input.right",
8547
+ id: "zhipu-quota",
8548
+ order: 40,
8549
+ locale: NS_ZHIPU,
8550
+ inject: (sessionId) => {
8551
+ const directory = ctx.modelDirectories.directoryFor(sessionId);
8552
+ return {
8553
+ directory: directory.store,
8554
+ loadModelDirectory: () => {
8555
+ directory.load().catch(() => void 0);
8556
+ }
8557
+ };
8558
+ }
8559
+ }, ZhipuComposerQuota));
6965
8560
  ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
6966
8561
  name: "tool.call.toolview",
6967
8562
  key: CODEX_IMAGE_TOOL_NAME,