@eddyskywalker/dsh-chatgpt-subscription 0.18.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +103 -1
  3. package/lib/client.js +1546 -269
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +9092 -2555
  6. package/lib/types/client/glm-coding-plan/GlmCodingPlanComposerQuota.d.ts +27 -0
  7. package/lib/types/client/glm-coding-plan/GlmCodingPlanComposerQuota.d.ts.map +1 -0
  8. package/lib/types/client/glm-coding-plan/GlmCodingPlanSection.d.ts +22 -0
  9. package/lib/types/client/glm-coding-plan/GlmCodingPlanSection.d.ts.map +1 -0
  10. package/lib/types/client/glm-coding-plan/api.d.ts +4 -0
  11. package/lib/types/client/glm-coding-plan/api.d.ts.map +1 -0
  12. package/lib/types/client/glm-coding-plan/locales.d.ts +412 -0
  13. package/lib/types/client/glm-coding-plan/locales.d.ts.map +1 -0
  14. package/lib/types/client/glm-coding-plan/styles.d.ts +15 -0
  15. package/lib/types/client/glm-coding-plan/styles.d.ts.map +1 -0
  16. package/lib/types/client/glm-coding-plan/useGlmCodingPlanSection.d.ts +65 -0
  17. package/lib/types/client/glm-coding-plan/useGlmCodingPlanSection.d.ts.map +1 -0
  18. package/lib/types/client/hub/brand-icons.d.ts +7 -5
  19. package/lib/types/client/hub/brand-icons.d.ts.map +1 -1
  20. package/lib/types/client/hub/providers.d.ts.map +1 -1
  21. package/lib/types/client/index.d.ts +2 -0
  22. package/lib/types/client/index.d.ts.map +1 -1
  23. package/lib/types/client/kimi-code/locales.d.ts +2 -2
  24. package/lib/types/client/minimax-code/locales.d.ts +2 -2
  25. package/lib/types/host/antigravity/oauth.d.ts +11 -1
  26. package/lib/types/host/antigravity/oauth.d.ts.map +1 -1
  27. package/lib/types/host/common/model-request-control.d.ts +1 -1
  28. package/lib/types/host/common/model-request-control.d.ts.map +1 -1
  29. package/lib/types/host/common/request-diagnostics.d.ts +1 -1
  30. package/lib/types/host/common/request-diagnostics.d.ts.map +1 -1
  31. package/lib/types/host/glm-coding-plan/account-pool.d.ts +152 -0
  32. package/lib/types/host/glm-coding-plan/account-pool.d.ts.map +1 -0
  33. package/lib/types/host/glm-coding-plan/adapter.d.ts +169 -0
  34. package/lib/types/host/glm-coding-plan/adapter.d.ts.map +1 -0
  35. package/lib/types/host/glm-coding-plan/adopt.d.ts +354 -0
  36. package/lib/types/host/glm-coding-plan/adopt.d.ts.map +1 -0
  37. package/lib/types/host/glm-coding-plan/biz-token-cache.d.ts +99 -0
  38. package/lib/types/host/glm-coding-plan/biz-token-cache.d.ts.map +1 -0
  39. package/lib/types/host/glm-coding-plan/client.d.ts +218 -0
  40. package/lib/types/host/glm-coding-plan/client.d.ts.map +1 -0
  41. package/lib/types/host/glm-coding-plan/exchange.d.ts +223 -0
  42. package/lib/types/host/glm-coding-plan/exchange.d.ts.map +1 -0
  43. package/lib/types/host/glm-coding-plan/mapper-anthropic.d.ts +308 -0
  44. package/lib/types/host/glm-coding-plan/mapper-anthropic.d.ts.map +1 -0
  45. package/lib/types/host/glm-coding-plan/mapper-openai.d.ts +213 -0
  46. package/lib/types/host/glm-coding-plan/mapper-openai.d.ts.map +1 -0
  47. package/lib/types/host/glm-coding-plan/model-catalog.d.ts +232 -0
  48. package/lib/types/host/glm-coding-plan/model-catalog.d.ts.map +1 -0
  49. package/lib/types/host/glm-coding-plan/oauth.d.ts +211 -0
  50. package/lib/types/host/glm-coding-plan/oauth.d.ts.map +1 -0
  51. package/lib/types/host/glm-coding-plan/routes.d.ts +93 -0
  52. package/lib/types/host/glm-coding-plan/routes.d.ts.map +1 -0
  53. package/lib/types/host/glm-coding-plan/signing.d.ts +323 -0
  54. package/lib/types/host/glm-coding-plan/signing.d.ts.map +1 -0
  55. package/lib/types/host/glm-coding-plan/token-store.d.ts +202 -0
  56. package/lib/types/host/glm-coding-plan/token-store.d.ts.map +1 -0
  57. package/lib/types/host/glm-coding-plan/types.d.ts +413 -0
  58. package/lib/types/host/glm-coding-plan/types.d.ts.map +1 -0
  59. package/lib/types/host/kimi-code/routes.d.ts +10 -0
  60. package/lib/types/host/kimi-code/routes.d.ts.map +1 -1
  61. package/lib/types/index.d.ts +9 -0
  62. package/lib/types/index.d.ts.map +1 -1
  63. package/lib/types/shared/glm-coding-plan-contracts.d.ts +315 -0
  64. package/lib/types/shared/glm-coding-plan-contracts.d.ts.map +1 -0
  65. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -383,6 +383,14 @@ window.__ModuleLoader__.load({
383
383
  * all — a wrong vendor's mark reads as a wrong answer, not a missing one
384
384
  * (the same principle claude-style's brand.js documents).
385
385
  */
386
+ /** 本文件自带的标记(BRAND_MARKS 之外的补充,按键索引)。 */
387
+ const LOCAL_MARKS = { glm: {
388
+ viewBox: "0 0 24 24",
389
+ body: "<text x=\"12\" y=\"16.4\" text-anchor=\"middle\" font-family=\"ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif\" font-size=\"10.6\" font-weight=\"700\" letter-spacing=\"0.2\" fill=\"currentColor\">GLM</text>"
390
+ } };
391
+ function artworkOf(mark) {
392
+ return mark in BRAND_MARKS ? BRAND_MARKS[mark] : LOCAL_MARKS[mark];
393
+ }
386
394
  const PROVIDER_BRANDS = {
387
395
  chatgpt: {
388
396
  mark: "openai",
@@ -411,6 +419,10 @@ window.__ModuleLoader__.load({
411
419
  mark: "minimax",
412
420
  tile: "#E2167E"
413
421
  },
422
+ "glm-coding-plan": {
423
+ mark: "glm",
424
+ tile: "#3859FF"
425
+ },
414
426
  claude: {
415
427
  mark: "claude",
416
428
  color: "#D97757",
@@ -424,7 +436,7 @@ window.__ModuleLoader__.load({
424
436
  };
425
437
  /** One brand mark at a given box size; the artwork is decorative. */
426
438
  function BrandMark({ mark, color, size = 22 }) {
427
- const art = BRAND_MARKS[mark];
439
+ const art = artworkOf(mark);
428
440
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
429
441
  "aria-hidden": "true",
430
442
  viewBox: art.viewBox,
@@ -465,6 +477,10 @@ window.__ModuleLoader__.load({
465
477
  * matching rule wins, so a specific rule ('kimi') precedes a looser one.
466
478
  */
467
479
  const MODEL_BRAND_RULES = [
480
+ {
481
+ re: /glm|zhipu|\bz\.ai\b/,
482
+ mark: "glm"
483
+ },
468
484
  {
469
485
  re: /gpt|codex|o[0-9]/,
470
486
  mark: "openai"
@@ -504,6 +520,23 @@ window.__ModuleLoader__.load({
504
520
  return null;
505
521
  }
506
522
  //#endregion
523
+ //#region src/shared/glm-coding-plan-contracts.ts
524
+ /** 线路 id。与用户自建的 `zai` / `zhipu` 兼容路由、已退役的 `zhipu-coding-plan` 都不同名(D1)。 */
525
+ const GLM_CODING_PLAN_PROVIDER_ID = "glm-coding-plan";
526
+ /** 设置卡片与 hub 卡片上显示的名字(D1)。 */
527
+ const GLM_CODING_PLAN_PROVIDER_NAME = "GLM(ZCode 账号)";
528
+ /**
529
+ * 路由前缀(host 暴露、client 消费)。
530
+ *
531
+ * 与其余各订阅线路一致:每条线路把自己的设置面挂在 `/<line>/api` 下,
532
+ * 不挂到 Codex 那条线路的 `/api/dsh-chatgpt-subscription` 前缀下面。
533
+ */
534
+ const GLM_CODING_PLAN_ROUTE_PREFIX = "/glm-coding-plan/api";
535
+ /** 区域参数是否落在这条线路认识的部署上(供 route 层校验自由输入的 region)。 */
536
+ function isGlmRegion(value) {
537
+ return value === "cn" || value === "intl";
538
+ }
539
+ //#endregion
507
540
  //#region src/shared/model-catalog.ts
508
541
  const GPT_56_MAX_CONTEXT_WINDOW = 1e6;
509
542
  const GPT_6_MAX_CONTEXT_WINDOW = 872e3;
@@ -664,14 +697,14 @@ window.__ModuleLoader__.load({
664
697
  return request$2(`${ROUTE_PREFIX}/status`);
665
698
  }
666
699
  startLogin() {
667
- return post$2(`${ROUTE_PREFIX}/login/start`, {});
700
+ return post$3(`${ROUTE_PREFIX}/login/start`, {});
668
701
  }
669
702
  cancelLogin(loginId) {
670
- return post$2(`${ROUTE_PREFIX}/login/cancel`, { loginId });
703
+ return post$3(`${ROUTE_PREFIX}/login/cancel`, { loginId });
671
704
  }
672
705
  /** Sign out one pooled account; without an id, the active one. */
673
706
  logout(accountId) {
674
- return post$2(`${ROUTE_PREFIX}/logout`, accountId === void 0 ? {} : { accountId });
707
+ return post$3(`${ROUTE_PREFIX}/logout`, accountId === void 0 ? {} : { accountId });
675
708
  }
676
709
  /**
677
710
  * One account-pool action, returning the refreshed status.
@@ -680,7 +713,7 @@ window.__ModuleLoader__.load({
680
713
  * never has to guess what the pool looks like after a change.
681
714
  */
682
715
  accountAction(action, body = {}) {
683
- return post$2(`${ROUTE_PREFIX}/accounts`, {
716
+ return post$3(`${ROUTE_PREFIX}/accounts`, {
684
717
  action,
685
718
  ...body
686
719
  });
@@ -695,32 +728,32 @@ window.__ModuleLoader__.load({
695
728
  * call the host always answers with a 400.
696
729
  */
697
730
  adoptLocalLogin(source) {
698
- return post$2(`${ROUTE_PREFIX}/adopt`, { source });
731
+ return post$3(`${ROUTE_PREFIX}/adopt`, { source });
699
732
  }
700
733
  /** Forget every imported snapshot. The CLIs' own files are never touched. */
701
734
  disableAdoptedLocalLogins() {
702
- return post$2(`${ROUTE_PREFIX}/adopt/disable`, {});
735
+ return post$3(`${ROUTE_PREFIX}/adopt/disable`, {});
703
736
  }
704
737
  refresh() {
705
- return post$2(`${ROUTE_PREFIX}/token/refresh`, {});
738
+ return post$3(`${ROUTE_PREFIX}/token/refresh`, {});
706
739
  }
707
740
  refreshQuota() {
708
- return post$2(`${ROUTE_PREFIX}/quota/refresh`, {});
741
+ return post$3(`${ROUTE_PREFIX}/quota/refresh`, {});
709
742
  }
710
743
  useResetCredit() {
711
- return post$2(`${ROUTE_PREFIX}/quota/reset-credit/use`, {});
744
+ return post$3(`${ROUTE_PREFIX}/quota/reset-credit/use`, {});
712
745
  }
713
746
  testConnection() {
714
- return post$2(`${ROUTE_PREFIX}/connection/test`, {});
747
+ return post$3(`${ROUTE_PREFIX}/connection/test`, {});
715
748
  }
716
749
  updatePreferences(patch) {
717
- return post$2(`${ROUTE_PREFIX}/preferences/update`, patch);
750
+ return post$3(`${ROUTE_PREFIX}/preferences/update`, patch);
718
751
  }
719
752
  events(loginId) {
720
753
  return new EventSource(`${ROUTE_PREFIX}/login/events?loginId=${encodeURIComponent(loginId)}`);
721
754
  }
722
755
  };
723
- async function post$2(url, body) {
756
+ async function post$3(url, body) {
724
757
  return request$2(url, {
725
758
  method: "POST",
726
759
  headers: { "content-type": "application/json" },
@@ -1241,7 +1274,7 @@ window.__ModuleLoader__.load({
1241
1274
  load(true);
1242
1275
  });
1243
1276
  } catch (cause) {
1244
- if (!quiet) setError(messageOf$1(cause));
1277
+ if (!quiet) setError(messageOf$2(cause));
1245
1278
  }
1246
1279
  }, []);
1247
1280
  (0, react.useEffect)(() => {
@@ -1302,7 +1335,7 @@ window.__ModuleLoader__.load({
1302
1335
  } catch (cause) {
1303
1336
  popup?.close();
1304
1337
  setBusy(null);
1305
- setError(messageOf$1(cause));
1338
+ setError(messageOf$2(cause));
1306
1339
  }
1307
1340
  };
1308
1341
  const cancelLogin = async () => {
@@ -1316,7 +1349,7 @@ window.__ModuleLoader__.load({
1316
1349
  setAuthUrl(null);
1317
1350
  await load();
1318
1351
  } catch (cause) {
1319
- setError(messageOf$1(cause));
1352
+ setError(messageOf$2(cause));
1320
1353
  } finally {
1321
1354
  setBusy(null);
1322
1355
  }
@@ -1502,7 +1535,7 @@ window.__ModuleLoader__.load({
1502
1535
  const next = await apiRef.current.accountAction("relogin", { accountId });
1503
1536
  setStatus(next);
1504
1537
  } catch (cause) {
1505
- setError(messageOf$1(cause));
1538
+ setError(messageOf$2(cause));
1506
1539
  return;
1507
1540
  }
1508
1541
  await startLogin();
@@ -1515,7 +1548,7 @@ window.__ModuleLoader__.load({
1515
1548
  try {
1516
1549
  await task();
1517
1550
  } catch (cause) {
1518
- setError(messageOf$1(cause));
1551
+ setError(messageOf$2(cause));
1519
1552
  } finally {
1520
1553
  setBusy(null);
1521
1554
  }
@@ -2253,7 +2286,7 @@ window.__ModuleLoader__.load({
2253
2286
  return absolute;
2254
2287
  }
2255
2288
  }
2256
- function messageOf$1(error) {
2289
+ function messageOf$2(error) {
2257
2290
  return error instanceof Error ? error.message : String(error);
2258
2291
  }
2259
2292
  //#endregion
@@ -2464,7 +2497,7 @@ window.__ModuleLoader__.load({
2464
2497
  //#endregion
2465
2498
  //#region src/client/antigravity/locales.ts
2466
2499
  const NS_ANTIGRAVITY = "dsh-antigravity";
2467
- const zh$7 = {
2500
+ const zh$8 = {
2468
2501
  ...accountPoolZh,
2469
2502
  title: "Antigravity",
2470
2503
  pageDesc: "登录 Google Antigravity / Cloud Code Assist,并查看当前账号的共享额度。",
@@ -2542,7 +2575,7 @@ window.__ModuleLoader__.load({
2542
2575
  loginFailed: "登录失败",
2543
2576
  tokens: "tokens"
2544
2577
  };
2545
- const en$7 = {
2578
+ const en$8 = {
2546
2579
  ...accountPoolEn,
2547
2580
  title: "Antigravity",
2548
2581
  pageDesc: "Sign in to Google Antigravity / Cloud Code Assist and view shared quotas.",
@@ -2620,15 +2653,15 @@ window.__ModuleLoader__.load({
2620
2653
  loginFailed: "Login failed",
2621
2654
  tokens: "tokens"
2622
2655
  };
2623
- const dictionaries$7 = {
2624
- zh: zh$7,
2625
- "zh-CN": zh$7,
2626
- en: en$7,
2627
- "en-US": en$7
2656
+ const dictionaries$8 = {
2657
+ zh: zh$8,
2658
+ "zh-CN": zh$8,
2659
+ en: en$8,
2660
+ "en-US": en$8
2628
2661
  };
2629
2662
  //#endregion
2630
2663
  //#region src/client/antigravity/AntigravitySection.tsx
2631
- const api$11 = createLineApi("/antigravity/api", "Antigravity");
2664
+ const api$12 = createLineApi("/antigravity/api", "Antigravity");
2632
2665
  /** A gap in human units, so the idle reading is legible without arithmetic. */
2633
2666
  function idleLabel(ms) {
2634
2667
  const seconds = Math.round(ms / 1e3);
@@ -2660,7 +2693,7 @@ window.__ModuleLoader__.load({
2660
2693
  const [savingModel, setSavingModel] = (0, react.useState)(null);
2661
2694
  /** Follow-up poll owed while the host refreshes the quota behind an answer. */
2662
2695
  const quotaFollowUp = (0, react.useRef)(null);
2663
- const t = zh$7;
2696
+ const t = zh$8;
2664
2697
  const notifyChange = (0, react.useCallback)(() => {
2665
2698
  onModelChange?.();
2666
2699
  loadModelDirectory?.();
@@ -2671,7 +2704,7 @@ window.__ModuleLoader__.load({
2671
2704
  setValidationUrl(null);
2672
2705
  }
2673
2706
  try {
2674
- const data = await api$11.request("/status");
2707
+ const data = await api$12.request("/status");
2675
2708
  setStatus(data);
2676
2709
  setContextDrafts(contextDraftsFor(data));
2677
2710
  quotaFollowUp.current ??= createQuotaFollowUp();
@@ -2703,11 +2736,11 @@ window.__ModuleLoader__.load({
2703
2736
  setError(null);
2704
2737
  setValidationUrl(null);
2705
2738
  setLoginProgress(null);
2706
- const flow = await api$11.request("/login", { method: "POST" });
2739
+ const flow = await api$12.request("/login", { method: "POST" });
2707
2740
  if (flow.authUrl) window.open(flow.authUrl, "_blank");
2708
2741
  const pollTimer = setInterval(async () => {
2709
2742
  try {
2710
- const pollStatus = await api$11.request("/login/status");
2743
+ const pollStatus = await api$12.request("/login/status");
2711
2744
  if (pollStatus.progress) setLoginProgress(pollStatus.progress);
2712
2745
  if (pollStatus.status === "complete") {
2713
2746
  clearInterval(pollTimer);
@@ -2739,7 +2772,7 @@ window.__ModuleLoader__.load({
2739
2772
  try {
2740
2773
  setBusy("quota");
2741
2774
  setError(null);
2742
- const updated = await api$11.request("/quota", { method: "POST" });
2775
+ const updated = await api$12.request("/quota", { method: "POST" });
2743
2776
  setStatus(updated);
2744
2777
  } catch (err) {
2745
2778
  setError(err instanceof Error ? err.message : String(err));
@@ -2751,7 +2784,7 @@ window.__ModuleLoader__.load({
2751
2784
  try {
2752
2785
  setBusy(`primary-${accountId}`);
2753
2786
  setError(null);
2754
- const updated = await api$11.request("/accounts", {
2787
+ const updated = await api$12.request("/accounts", {
2755
2788
  method: "POST",
2756
2789
  body: JSON.stringify({
2757
2790
  action: "set-primary",
@@ -2770,7 +2803,7 @@ window.__ModuleLoader__.load({
2770
2803
  try {
2771
2804
  setBusy(`delete-${accountId}`);
2772
2805
  setError(null);
2773
- const updated = await api$11.request("/accounts", {
2806
+ const updated = await api$12.request("/accounts", {
2774
2807
  method: "POST",
2775
2808
  body: JSON.stringify({
2776
2809
  action: "delete",
@@ -2789,7 +2822,7 @@ window.__ModuleLoader__.load({
2789
2822
  try {
2790
2823
  setBusy(`cooldown-${accountId}`);
2791
2824
  setError(null);
2792
- const updated = await api$11.request("/accounts", {
2825
+ const updated = await api$12.request("/accounts", {
2793
2826
  method: "POST",
2794
2827
  body: JSON.stringify({
2795
2828
  action: "clear-cooldown",
@@ -2807,7 +2840,7 @@ window.__ModuleLoader__.load({
2807
2840
  try {
2808
2841
  setBusy("strategy");
2809
2842
  setError(null);
2810
- const updated = await api$11.request("/accounts", {
2843
+ const updated = await api$12.request("/accounts", {
2811
2844
  method: "POST",
2812
2845
  body: JSON.stringify({
2813
2846
  action: "strategy",
@@ -2826,7 +2859,7 @@ window.__ModuleLoader__.load({
2826
2859
  const currentEnabled = status.models.filter((m) => m.enabled).map((m) => m.id);
2827
2860
  const nextEnabled = checked ? [.../* @__PURE__ */ new Set([...currentEnabled, modelId])] : currentEnabled.filter((id) => id !== modelId);
2828
2861
  try {
2829
- const updated = await api$11.request("/models", {
2862
+ const updated = await api$12.request("/models", {
2830
2863
  method: "POST",
2831
2864
  body: JSON.stringify({ enabledModelIds: nextEnabled })
2832
2865
  });
@@ -2841,7 +2874,7 @@ window.__ModuleLoader__.load({
2841
2874
  if (!status) return;
2842
2875
  const nextEnabled = selectAll ? status.models.map((m) => m.id) : [];
2843
2876
  try {
2844
- const updated = await api$11.request("/models", {
2877
+ const updated = await api$12.request("/models", {
2845
2878
  method: "POST",
2846
2879
  body: JSON.stringify({ enabledModelIds: nextEnabled })
2847
2880
  });
@@ -2854,7 +2887,7 @@ window.__ModuleLoader__.load({
2854
2887
  };
2855
2888
  const handleUpdateEffort = async (effort) => {
2856
2889
  try {
2857
- const updated = await api$11.request("/settings", {
2890
+ const updated = await api$12.request("/settings", {
2858
2891
  method: "POST",
2859
2892
  body: JSON.stringify({ defaultReasoningEffort: effort })
2860
2893
  });
@@ -2874,7 +2907,7 @@ window.__ModuleLoader__.load({
2874
2907
  try {
2875
2908
  setSavingModel(modelId);
2876
2909
  setError(null);
2877
- const updated = await api$11.request("/settings", {
2910
+ const updated = await api$12.request("/settings", {
2878
2911
  method: "POST",
2879
2912
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
2880
2913
  });
@@ -2895,7 +2928,7 @@ window.__ModuleLoader__.load({
2895
2928
  try {
2896
2929
  setSavingModel(modelId);
2897
2930
  setError(null);
2898
- const updated = await api$11.request("/settings", {
2931
+ const updated = await api$12.request("/settings", {
2899
2932
  method: "POST",
2900
2933
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
2901
2934
  });
@@ -2922,7 +2955,7 @@ window.__ModuleLoader__.load({
2922
2955
  try {
2923
2956
  setBusy("context");
2924
2957
  setError(null);
2925
- const updated = await api$11.request("/settings", {
2958
+ const updated = await api$12.request("/settings", {
2926
2959
  method: "POST",
2927
2960
  body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
2928
2961
  });
@@ -3217,7 +3250,7 @@ window.__ModuleLoader__.load({
3217
3250
  //#endregion
3218
3251
  //#region src/client/command-code/locales.ts
3219
3252
  const NS_COMMAND_CODE = "dsh-command-code";
3220
- const zh$6 = {
3253
+ const zh$7 = {
3221
3254
  ...accountPoolZh,
3222
3255
  title: "Command Code",
3223
3256
  pageDesc: "登录 Command Code,管理可用模型、上下文窗口与额度。",
@@ -3285,7 +3318,7 @@ window.__ModuleLoader__.load({
3285
3318
  loginFailed: "登录失败",
3286
3319
  tokens: "tokens"
3287
3320
  };
3288
- const en$6 = {
3321
+ const en$7 = {
3289
3322
  ...accountPoolEn,
3290
3323
  title: "Command Code",
3291
3324
  pageDesc: "Sign in to Command Code and manage models, context windows, and quota.",
@@ -3353,11 +3386,11 @@ window.__ModuleLoader__.load({
3353
3386
  loginFailed: "Sign-in failed",
3354
3387
  tokens: "tokens"
3355
3388
  };
3356
- const dictionaries$6 = {
3357
- zh: zh$6,
3358
- "zh-CN": zh$6,
3359
- en: en$6,
3360
- "en-US": en$6
3389
+ const dictionaries$7 = {
3390
+ zh: zh$7,
3391
+ "zh-CN": zh$7,
3392
+ en: en$7,
3393
+ "en-US": en$7
3361
3394
  };
3362
3395
  //#endregion
3363
3396
  //#region src/client/command-code/CommandCodeSection.tsx
@@ -3374,7 +3407,7 @@ window.__ModuleLoader__.load({
3374
3407
  xhigh: "X-High",
3375
3408
  max: "Max"
3376
3409
  };
3377
- const api$10 = createLineApi("/command-code/api", "Command Code");
3410
+ const api$11 = createLineApi("/command-code/api", "Command Code");
3378
3411
  /**
3379
3412
  * Route name shown next to a model.
3380
3413
  *
@@ -3398,7 +3431,7 @@ window.__ModuleLoader__.load({
3398
3431
  const [apiKey, setApiKey] = (0, react.useState)("");
3399
3432
  /** Follow-up poll owed while the host refreshes the quota behind an answer. */
3400
3433
  const quotaFollowUp = (0, react.useRef)(null);
3401
- const t = zh$6;
3434
+ const t = zh$7;
3402
3435
  const notifyChange = (0, react.useCallback)(() => {
3403
3436
  onModelChange?.();
3404
3437
  loadModelDirectory?.();
@@ -3406,7 +3439,7 @@ window.__ModuleLoader__.load({
3406
3439
  const loadStatus = (0, react.useCallback)(async (quiet = false) => {
3407
3440
  if (!quiet) setError(null);
3408
3441
  try {
3409
- const data = await api$10.request("/status");
3442
+ const data = await api$11.request("/status");
3410
3443
  setStatus(data);
3411
3444
  setContextDrafts(contextDraftsFor(data));
3412
3445
  quotaFollowUp.current ??= createQuotaFollowUp();
@@ -3437,12 +3470,12 @@ window.__ModuleLoader__.load({
3437
3470
  setBusy("login");
3438
3471
  setError(null);
3439
3472
  setLoginProgress(null);
3440
- const flow = await api$10.request("/login", { method: "POST" });
3473
+ const flow = await api$11.request("/login", { method: "POST" });
3441
3474
  if (flow.authUrl) window.open(flow.authUrl, "_blank");
3442
3475
  const pollTimer = window.setInterval(() => {
3443
3476
  (async () => {
3444
3477
  try {
3445
- const poll = await api$10.request("/login/status");
3478
+ const poll = await api$11.request("/login/status");
3446
3479
  if (poll.progress) setLoginProgress(poll.progress);
3447
3480
  if (poll.status === "complete") {
3448
3481
  window.clearInterval(pollTimer);
@@ -3474,7 +3507,7 @@ window.__ModuleLoader__.load({
3474
3507
  try {
3475
3508
  setBusy("apikey");
3476
3509
  setError(null);
3477
- const updated = await api$10.request("/login/apikey", {
3510
+ const updated = await api$11.request("/login/apikey", {
3478
3511
  method: "POST",
3479
3512
  body: JSON.stringify({ apiKey })
3480
3513
  });
@@ -3492,7 +3525,7 @@ window.__ModuleLoader__.load({
3492
3525
  try {
3493
3526
  setBusy(`${action}-${accountId}`);
3494
3527
  setError(null);
3495
- const updated = await api$10.request("/accounts", {
3528
+ const updated = await api$11.request("/accounts", {
3496
3529
  method: "POST",
3497
3530
  body: JSON.stringify({
3498
3531
  action,
@@ -3511,7 +3544,7 @@ window.__ModuleLoader__.load({
3511
3544
  try {
3512
3545
  setBusy("strategy");
3513
3546
  setError(null);
3514
- const updated = await api$10.request("/accounts", {
3547
+ const updated = await api$11.request("/accounts", {
3515
3548
  method: "POST",
3516
3549
  body: JSON.stringify({
3517
3550
  action: "strategy",
@@ -3534,7 +3567,7 @@ window.__ModuleLoader__.load({
3534
3567
  const handleRelogin = (accountId) => {
3535
3568
  (async () => {
3536
3569
  try {
3537
- const updated = await api$10.request("/accounts", {
3570
+ const updated = await api$11.request("/accounts", {
3538
3571
  method: "POST",
3539
3572
  body: JSON.stringify({
3540
3573
  action: "relogin",
@@ -3553,7 +3586,7 @@ window.__ModuleLoader__.load({
3553
3586
  try {
3554
3587
  setBusy("quota");
3555
3588
  setError(null);
3556
- const updated = await api$10.request("/quota", { method: "POST" });
3589
+ const updated = await api$11.request("/quota", { method: "POST" });
3557
3590
  setStatus(updated);
3558
3591
  } catch (err) {
3559
3592
  setError(err instanceof Error ? err.message : String(err));
@@ -3565,7 +3598,7 @@ window.__ModuleLoader__.load({
3565
3598
  try {
3566
3599
  setBusy("catalog");
3567
3600
  setError(null);
3568
- const updated = await api$10.request("/catalog/refresh", { method: "POST" });
3601
+ const updated = await api$11.request("/catalog/refresh", { method: "POST" });
3569
3602
  setStatus(updated);
3570
3603
  setContextDrafts(contextDraftsFor(updated));
3571
3604
  notifyChange();
@@ -3579,7 +3612,7 @@ window.__ModuleLoader__.load({
3579
3612
  try {
3580
3613
  setBusy("connection");
3581
3614
  setError(null);
3582
- await api$10.post("/connection/test");
3615
+ await api$11.post("/connection/test");
3583
3616
  await loadStatus(true);
3584
3617
  } catch (err) {
3585
3618
  setError(err instanceof Error ? err.message : String(err));
@@ -3589,7 +3622,7 @@ window.__ModuleLoader__.load({
3589
3622
  };
3590
3623
  const applyEnabled = async (enabledModelIds) => {
3591
3624
  try {
3592
- const updated = await api$10.request("/models", {
3625
+ const updated = await api$11.request("/models", {
3593
3626
  method: "POST",
3594
3627
  body: JSON.stringify({ enabledModelIds })
3595
3628
  });
@@ -3612,7 +3645,7 @@ window.__ModuleLoader__.load({
3612
3645
  };
3613
3646
  const handleUpdateEffort = async (effort) => {
3614
3647
  try {
3615
- const updated = await api$10.request("/settings", {
3648
+ const updated = await api$11.request("/settings", {
3616
3649
  method: "POST",
3617
3650
  body: JSON.stringify({ defaultReasoningEffort: effort })
3618
3651
  });
@@ -3632,7 +3665,7 @@ window.__ModuleLoader__.load({
3632
3665
  try {
3633
3666
  setSavingModel(modelId);
3634
3667
  setError(null);
3635
- const updated = await api$10.request("/settings", {
3668
+ const updated = await api$11.request("/settings", {
3636
3669
  method: "POST",
3637
3670
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
3638
3671
  });
@@ -3653,7 +3686,7 @@ window.__ModuleLoader__.load({
3653
3686
  try {
3654
3687
  setSavingModel(modelId);
3655
3688
  setError(null);
3656
- const updated = await api$10.request("/settings", {
3689
+ const updated = await api$11.request("/settings", {
3657
3690
  method: "POST",
3658
3691
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
3659
3692
  });
@@ -3680,7 +3713,7 @@ window.__ModuleLoader__.load({
3680
3713
  try {
3681
3714
  setBusy("context");
3682
3715
  setError(null);
3683
- const updated = await api$10.request("/settings", {
3716
+ const updated = await api$11.request("/settings", {
3684
3717
  method: "POST",
3685
3718
  body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
3686
3719
  });
@@ -3979,7 +4012,7 @@ window.__ModuleLoader__.load({
3979
4012
  //#endregion
3980
4013
  //#region src/client/kimi-code/locales.ts
3981
4014
  const NS_KIMI_CODE = "dsh-kimi-code";
3982
- const zh$5 = {
4015
+ const zh$6 = {
3983
4016
  ...accountPoolZh,
3984
4017
  title: "Kimi Code",
3985
4018
  pageDesc: "登录 Kimi Code 订阅,管理模型、思考档位、上下文窗口与额度。",
@@ -4102,7 +4135,7 @@ window.__ModuleLoader__.load({
4102
4135
  requests: "次请求",
4103
4136
  tokens: "tokens"
4104
4137
  };
4105
- const en$5 = {
4138
+ const en$6 = {
4106
4139
  ...accountPoolEn,
4107
4140
  title: "Kimi Code",
4108
4141
  pageDesc: "Sign in to the Kimi Code subscription and manage models, thinking level, context windows, and quota.",
@@ -4225,11 +4258,11 @@ window.__ModuleLoader__.load({
4225
4258
  requests: "requests",
4226
4259
  tokens: "tokens"
4227
4260
  };
4228
- const dictionaries$5 = {
4229
- zh: zh$5,
4230
- "zh-CN": zh$5,
4231
- en: en$5,
4232
- "en-US": en$5
4261
+ const dictionaries$6 = {
4262
+ zh: zh$6,
4263
+ "zh-CN": zh$6,
4264
+ en: en$6,
4265
+ "en-US": en$6
4233
4266
  };
4234
4267
  //#endregion
4235
4268
  //#region src/client/kimi-code/KimiModelCapabilities.tsx
@@ -4242,7 +4275,7 @@ window.__ModuleLoader__.load({
4242
4275
  * Capabilities are now short tags in their own columns, with the per-model
4243
4276
  * detail kept in a hover title.
4244
4277
  */
4245
- const t = zh$5;
4278
+ const t = zh$6;
4246
4279
  function KimiModelCapabilities({ models }) {
4247
4280
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4248
4281
  className: "dsha-cap-table",
@@ -4290,7 +4323,7 @@ window.__ModuleLoader__.load({
4290
4323
  }
4291
4324
  //#endregion
4292
4325
  //#region src/client/kimi-code/KimiCodeSection.tsx
4293
- const api$9 = createLineApi("/kimi-code/api", "Kimi Code");
4326
+ const api$10 = createLineApi("/kimi-code/api", "Kimi Code");
4294
4327
  /** Money the service reports in minor units, rendered in its own currency. */
4295
4328
  function formatMoney(cents, currency) {
4296
4329
  if (cents === null) return "—";
@@ -4305,10 +4338,10 @@ window.__ModuleLoader__.load({
4305
4338
  }
4306
4339
  }
4307
4340
  const EFFORT_LABEL = {
4308
- low: zh$5.effortLow,
4309
- high: zh$5.effortHigh,
4310
- max: zh$5.effortMax,
4311
- none: zh$5.effortNone
4341
+ low: zh$6.effortLow,
4342
+ high: zh$6.effortHigh,
4343
+ max: zh$6.effortMax,
4344
+ none: zh$6.effortNone
4312
4345
  };
4313
4346
  /** Human label for the last request's prefix-drift cause. */
4314
4347
  function driftLabel(cause, t) {
@@ -4334,7 +4367,7 @@ window.__ModuleLoader__.load({
4334
4367
  const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
4335
4368
  /** Follow-up poll owed while the host refreshes the quota behind an answer. */
4336
4369
  const quotaFollowUp = (0, react.useRef)(null);
4337
- const t = zh$5;
4370
+ const t = zh$6;
4338
4371
  const notifyChange = (0, react.useCallback)(() => {
4339
4372
  onModelChange?.();
4340
4373
  loadModelDirectory?.();
@@ -4342,7 +4375,7 @@ window.__ModuleLoader__.load({
4342
4375
  const loadStatus = (0, react.useCallback)(async (quiet = false) => {
4343
4376
  if (!quiet) setError(null);
4344
4377
  try {
4345
- const data = await api$9.request("/status");
4378
+ const data = await api$10.request("/status");
4346
4379
  setStatus(data);
4347
4380
  setContextDrafts(contextDraftsFor(data));
4348
4381
  quotaFollowUp.current ??= createQuotaFollowUp();
@@ -4373,7 +4406,7 @@ window.__ModuleLoader__.load({
4373
4406
  const timer = window.setInterval(() => {
4374
4407
  (async () => {
4375
4408
  try {
4376
- const poll = await api$9.request("/login/status");
4409
+ const poll = await api$10.request("/login/status");
4377
4410
  setFlow(poll);
4378
4411
  if (poll.status === "complete") {
4379
4412
  await loadStatus();
@@ -4394,7 +4427,7 @@ window.__ModuleLoader__.load({
4394
4427
  setBusy("login");
4395
4428
  setError(null);
4396
4429
  setCopied(false);
4397
- const next = await api$9.request("/login", {
4430
+ const next = await api$10.request("/login", {
4398
4431
  method: "POST",
4399
4432
  body: JSON.stringify({})
4400
4433
  });
@@ -4407,7 +4440,7 @@ window.__ModuleLoader__.load({
4407
4440
  };
4408
4441
  const handleCancelLogin = async () => {
4409
4442
  try {
4410
- await api$9.request("/login/cancel", { method: "POST" });
4443
+ await api$10.request("/login/cancel", { method: "POST" });
4411
4444
  setFlow({ status: "idle" });
4412
4445
  } catch (err) {
4413
4446
  setError(err instanceof Error ? err.message : String(err));
@@ -4427,7 +4460,7 @@ window.__ModuleLoader__.load({
4427
4460
  try {
4428
4461
  setBusy(`${action}-${accountId}`);
4429
4462
  setError(null);
4430
- const updated = await api$9.request("/accounts", {
4463
+ const updated = await api$10.request("/accounts", {
4431
4464
  method: "POST",
4432
4465
  body: JSON.stringify({
4433
4466
  action,
@@ -4447,7 +4480,7 @@ window.__ModuleLoader__.load({
4447
4480
  try {
4448
4481
  setBusy("strategy");
4449
4482
  setError(null);
4450
- const updated = await api$9.request("/accounts", {
4483
+ const updated = await api$10.request("/accounts", {
4451
4484
  method: "POST",
4452
4485
  body: JSON.stringify({
4453
4486
  action: "strategy",
@@ -4470,7 +4503,7 @@ window.__ModuleLoader__.load({
4470
4503
  const handleRelogin = (accountId) => {
4471
4504
  (async () => {
4472
4505
  try {
4473
- const updated = await api$9.request("/accounts", {
4506
+ const updated = await api$10.request("/accounts", {
4474
4507
  method: "POST",
4475
4508
  body: JSON.stringify({
4476
4509
  action: "relogin",
@@ -4489,7 +4522,7 @@ window.__ModuleLoader__.load({
4489
4522
  try {
4490
4523
  setBusy("quota");
4491
4524
  setError(null);
4492
- const updated = await api$9.request("/quota", { method: "POST" });
4525
+ const updated = await api$10.request("/quota", { method: "POST" });
4493
4526
  setStatus(updated);
4494
4527
  } catch (err) {
4495
4528
  setError(err instanceof Error ? err.message : String(err));
@@ -4502,7 +4535,7 @@ window.__ModuleLoader__.load({
4502
4535
  try {
4503
4536
  setBusy("catalog");
4504
4537
  setError(null);
4505
- const updated = await api$9.request("/catalog/refresh", { method: "POST" });
4538
+ const updated = await api$10.request("/catalog/refresh", { method: "POST" });
4506
4539
  setStatus(updated);
4507
4540
  setContextDrafts(contextDraftsFor(updated));
4508
4541
  notifyChange();
@@ -4517,7 +4550,7 @@ window.__ModuleLoader__.load({
4517
4550
  setBusy("connection");
4518
4551
  setError(null);
4519
4552
  setConnectionNotice(null);
4520
- const result = await api$9.request("/connection/test", { method: "POST" });
4553
+ const result = await api$10.request("/connection/test", { method: "POST" });
4521
4554
  setConnectionNotice(result.connected ? `${t.testSuccess} · ${result.latencyMs} ms` : t.testFailed);
4522
4555
  await loadStatus(true);
4523
4556
  } catch (err) {
@@ -4528,7 +4561,7 @@ window.__ModuleLoader__.load({
4528
4561
  };
4529
4562
  const applyEnabled = async (enabledModelIds) => {
4530
4563
  try {
4531
- const updated = await api$9.request("/models", {
4564
+ const updated = await api$10.request("/models", {
4532
4565
  method: "POST",
4533
4566
  body: JSON.stringify({ enabledModelIds })
4534
4567
  });
@@ -4551,7 +4584,7 @@ window.__ModuleLoader__.load({
4551
4584
  };
4552
4585
  const handleUpdateEffort = async (effort) => {
4553
4586
  try {
4554
- const updated = await api$9.request("/settings", {
4587
+ const updated = await api$10.request("/settings", {
4555
4588
  method: "POST",
4556
4589
  body: JSON.stringify({ defaultReasoningEffort: effort })
4557
4590
  });
@@ -4563,7 +4596,7 @@ window.__ModuleLoader__.load({
4563
4596
  };
4564
4597
  const handleUpdateCacheTtl = async (ttl) => {
4565
4598
  try {
4566
- const updated = await api$9.request("/settings", {
4599
+ const updated = await api$10.request("/settings", {
4567
4600
  method: "POST",
4568
4601
  body: JSON.stringify({ cacheTtl: ttl })
4569
4602
  });
@@ -4583,7 +4616,7 @@ window.__ModuleLoader__.load({
4583
4616
  try {
4584
4617
  setSavingModel(modelId);
4585
4618
  setError(null);
4586
- const updated = await api$9.request("/settings", {
4619
+ const updated = await api$10.request("/settings", {
4587
4620
  method: "POST",
4588
4621
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
4589
4622
  });
@@ -4604,7 +4637,7 @@ window.__ModuleLoader__.load({
4604
4637
  try {
4605
4638
  setSavingModel(modelId);
4606
4639
  setError(null);
4607
- const updated = await api$9.request("/settings", {
4640
+ const updated = await api$10.request("/settings", {
4608
4641
  method: "POST",
4609
4642
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
4610
4643
  });
@@ -4631,7 +4664,7 @@ window.__ModuleLoader__.load({
4631
4664
  try {
4632
4665
  setBusy("context");
4633
4666
  setError(null);
4634
- const updated = await api$9.request("/settings", {
4667
+ const updated = await api$10.request("/settings", {
4635
4668
  method: "POST",
4636
4669
  body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
4637
4670
  });
@@ -5088,7 +5121,7 @@ window.__ModuleLoader__.load({
5088
5121
  //#endregion
5089
5122
  //#region src/client/workbuddy/locales.ts
5090
5123
  const NS_WORKBUDDY = "dsh-workbuddy";
5091
- const zh$4 = {
5124
+ const zh$5 = {
5092
5125
  title: "WorkBuddy",
5093
5126
  pageDesc: "复用本机 CodeBuddy 桌面端登录态,管理 WorkBuddy(CodeBuddy 订阅)模型、上下文窗口与额度。",
5094
5127
  account: "账号",
@@ -5174,7 +5207,7 @@ window.__ModuleLoader__.load({
5174
5207
  checkinNow: "立即签到",
5175
5208
  checkinRunning: "签到中…"
5176
5209
  };
5177
- const en$4 = {
5210
+ const en$5 = {
5178
5211
  title: "WorkBuddy",
5179
5212
  pageDesc: "Reuse the local CodeBuddy desktop sign-in to manage WorkBuddy (CodeBuddy subscription) models, context windows, and quota.",
5180
5213
  account: "Account",
@@ -5260,11 +5293,11 @@ window.__ModuleLoader__.load({
5260
5293
  checkinNow: "Check in now",
5261
5294
  checkinRunning: "Checking in…"
5262
5295
  };
5263
- const dictionaries$4 = {
5264
- zh: zh$4,
5265
- "zh-CN": zh$4,
5266
- en: en$4,
5267
- "en-US": en$4
5296
+ const dictionaries$5 = {
5297
+ zh: zh$5,
5298
+ "zh-CN": zh$5,
5299
+ en: en$5,
5300
+ "en-US": en$5
5268
5301
  };
5269
5302
  //#endregion
5270
5303
  //#region src/client/workbuddy/useWorkBuddySection.ts
@@ -5300,7 +5333,7 @@ window.__ModuleLoader__.load({
5300
5333
  * is exactly what a stale host half produces) be reported as such instead of as
5301
5334
  * a bare "Unexpected end of JSON input".
5302
5335
  */
5303
- const api$8 = createLineApi(API$2, "WorkBuddy");
5336
+ const api$9 = createLineApi(API$2, "WorkBuddy");
5304
5337
  /**
5305
5338
  * Reasoning levels the default-effort control may offer.
5306
5339
  *
@@ -5357,7 +5390,7 @@ window.__ModuleLoader__.load({
5357
5390
  const quotaFollowUp = (0, react.useRef)(null);
5358
5391
  const [contextDrafts, setContextDrafts] = (0, react.useState)({});
5359
5392
  const [savingModel, setSavingModel] = (0, react.useState)(null);
5360
- const t = zh$4;
5393
+ const t = zh$5;
5361
5394
  const notifyChange = (0, react.useCallback)(() => {
5362
5395
  onModelChange?.();
5363
5396
  loadModelDirectory?.();
@@ -5369,7 +5402,7 @@ window.__ModuleLoader__.load({
5369
5402
  const loadStatus = (0, react.useCallback)(async (quiet = false) => {
5370
5403
  if (!quiet) setError(null);
5371
5404
  try {
5372
- const data = await api$8.request("/status");
5405
+ const data = await api$9.request("/status");
5373
5406
  const normalized = normalizeStatus(data);
5374
5407
  setStatus(normalized);
5375
5408
  setStatusFailed(false);
@@ -5402,7 +5435,7 @@ window.__ModuleLoader__.load({
5402
5435
  try {
5403
5436
  setBusy("rescan");
5404
5437
  setError(null);
5405
- const updated = await api$8.request("/rescan", { method: "POST" });
5438
+ const updated = await api$9.request("/rescan", { method: "POST" });
5406
5439
  setStatus(normalizeStatus(updated));
5407
5440
  notifyChange();
5408
5441
  } catch (err) {
@@ -5416,7 +5449,7 @@ window.__ModuleLoader__.load({
5416
5449
  setBusy(`login:${region}`);
5417
5450
  setError(null);
5418
5451
  setLoginProgress(t.loginWaiting);
5419
- const flow = await api$8.request("/accounts/login", {
5452
+ const flow = await api$9.request("/accounts/login", {
5420
5453
  method: "POST",
5421
5454
  body: JSON.stringify({ region })
5422
5455
  });
@@ -5426,7 +5459,7 @@ window.__ModuleLoader__.load({
5426
5459
  const timer = window.setInterval(() => {
5427
5460
  (async () => {
5428
5461
  try {
5429
- const poll = await api$8.request("/accounts/login/status");
5462
+ const poll = await api$9.request("/accounts/login/status");
5430
5463
  if (poll.progress) setLoginProgress(poll.progress);
5431
5464
  if (poll.status === "complete") {
5432
5465
  window.clearInterval(timer);
@@ -5435,7 +5468,7 @@ window.__ModuleLoader__.load({
5435
5468
  loginTimeoutRef.current = null;
5436
5469
  setBusy(null);
5437
5470
  setLoginProgress(null);
5438
- if (poll.accountId) await api$8.request("/settings", {
5471
+ if (poll.accountId) await api$9.request("/settings", {
5439
5472
  method: "POST",
5440
5473
  body: JSON.stringify({ selectedAccountId: poll.accountId })
5441
5474
  });
@@ -5475,7 +5508,7 @@ window.__ModuleLoader__.load({
5475
5508
  try {
5476
5509
  setBusy(`${action}:${accountId}`);
5477
5510
  setError(null);
5478
- const updated = await api$8.request("/accounts/action", {
5511
+ const updated = await api$9.request("/accounts/action", {
5479
5512
  method: "POST",
5480
5513
  body: JSON.stringify({
5481
5514
  action,
@@ -5498,7 +5531,7 @@ window.__ModuleLoader__.load({
5498
5531
  try {
5499
5532
  setBusy("strategy");
5500
5533
  setError(null);
5501
- const updated = await api$8.request("/accounts/strategy", {
5534
+ const updated = await api$9.request("/accounts/strategy", {
5502
5535
  method: "POST",
5503
5536
  body: JSON.stringify({ strategy })
5504
5537
  });
@@ -5513,7 +5546,7 @@ window.__ModuleLoader__.load({
5513
5546
  try {
5514
5547
  setBusy("connection");
5515
5548
  setError(null);
5516
- setConnection(await api$8.request("/connection/test", { method: "POST" }));
5549
+ setConnection(await api$9.request("/connection/test", { method: "POST" }));
5517
5550
  } catch (err) {
5518
5551
  setError(err instanceof Error ? err.message : String(err));
5519
5552
  } finally {
@@ -5524,7 +5557,7 @@ window.__ModuleLoader__.load({
5524
5557
  try {
5525
5558
  setBusy("quota");
5526
5559
  setError(null);
5527
- const updated = await api$8.request("/quota", { method: "POST" });
5560
+ const updated = await api$9.request("/quota", { method: "POST" });
5528
5561
  setStatus(updated);
5529
5562
  } catch (err) {
5530
5563
  setError(err instanceof Error ? err.message : String(err));
@@ -5536,7 +5569,7 @@ window.__ModuleLoader__.load({
5536
5569
  try {
5537
5570
  setBusy("checkin");
5538
5571
  setError(null);
5539
- const updated = await api$8.request("/checkin/now", { method: "POST" });
5572
+ const updated = await api$9.request("/checkin/now", { method: "POST" });
5540
5573
  setStatus(normalizeStatus(updated));
5541
5574
  } catch (err) {
5542
5575
  setError(err instanceof Error ? err.message : String(err));
@@ -5548,7 +5581,7 @@ window.__ModuleLoader__.load({
5548
5581
  try {
5549
5582
  setBusy("checkin");
5550
5583
  setError(null);
5551
- const updated = await api$8.request("/settings", {
5584
+ const updated = await api$9.request("/settings", {
5552
5585
  method: "POST",
5553
5586
  body: JSON.stringify({ checkin })
5554
5587
  });
@@ -5566,7 +5599,7 @@ window.__ModuleLoader__.load({
5566
5599
  try {
5567
5600
  setBusy(`model:${modelId}`);
5568
5601
  setError(null);
5569
- const normalized = normalizeStatus(await api$8.request("/settings", {
5602
+ const normalized = normalizeStatus(await api$9.request("/settings", {
5570
5603
  method: "POST",
5571
5604
  body: JSON.stringify({ enabledModelIds: next })
5572
5605
  }));
@@ -5584,7 +5617,7 @@ window.__ModuleLoader__.load({
5584
5617
  try {
5585
5618
  setBusy("models-all");
5586
5619
  setError(null);
5587
- const normalized = normalizeStatus(await api$8.request("/settings", {
5620
+ const normalized = normalizeStatus(await api$9.request("/settings", {
5588
5621
  method: "POST",
5589
5622
  body: JSON.stringify({ enabledModelIds: enabled ? status.models.map((model) => model.id) : [] })
5590
5623
  }));
@@ -5601,7 +5634,7 @@ window.__ModuleLoader__.load({
5601
5634
  try {
5602
5635
  setBusy("effort");
5603
5636
  setError(null);
5604
- const updated = await api$8.request("/settings", {
5637
+ const updated = await api$9.request("/settings", {
5605
5638
  method: "POST",
5606
5639
  body: JSON.stringify({ defaultReasoningEffort: effort })
5607
5640
  });
@@ -5617,7 +5650,7 @@ window.__ModuleLoader__.load({
5617
5650
  try {
5618
5651
  setBusy("catalog");
5619
5652
  setError(null);
5620
- const normalized = normalizeStatus(await api$8.request("/catalog/refresh", { method: "POST" }));
5653
+ const normalized = normalizeStatus(await api$9.request("/catalog/refresh", { method: "POST" }));
5621
5654
  setStatus(normalized);
5622
5655
  setContextDrafts(contextDraftsFor(normalized));
5623
5656
  notifyChange();
@@ -5637,7 +5670,7 @@ window.__ModuleLoader__.load({
5637
5670
  try {
5638
5671
  setSavingModel(modelId);
5639
5672
  setError(null);
5640
- const updated = await api$8.request("/settings", {
5673
+ const updated = await api$9.request("/settings", {
5641
5674
  method: "POST",
5642
5675
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
5643
5676
  });
@@ -5658,7 +5691,7 @@ window.__ModuleLoader__.load({
5658
5691
  try {
5659
5692
  setSavingModel(modelId);
5660
5693
  setError(null);
5661
- const updated = normalizeStatus(await api$8.request("/settings", {
5694
+ const updated = normalizeStatus(await api$9.request("/settings", {
5662
5695
  method: "POST",
5663
5696
  body: JSON.stringify({ contextWindowOverrides: { [modelId]: null } })
5664
5697
  }));
@@ -5685,7 +5718,7 @@ window.__ModuleLoader__.load({
5685
5718
  try {
5686
5719
  setBusy("context");
5687
5720
  setError(null);
5688
- const updated = normalizeStatus(await api$8.request("/settings", {
5721
+ const updated = normalizeStatus(await api$9.request("/settings", {
5689
5722
  method: "POST",
5690
5723
  body: JSON.stringify({ contextWindowOverrides: Object.fromEntries(models.map((model) => [model, null])) })
5691
5724
  }));
@@ -5833,7 +5866,7 @@ window.__ModuleLoader__.load({
5833
5866
  const { status, loading, busy, error, connection, loginProgress, contextDrafts, savingModel } = state;
5834
5867
  const { poolAccounts, effortChoices, allModels, strayEffort, contextModels, overrideCount, quota, authenticated, unreachable, poolLabels } = derived;
5835
5868
  const { login, rescan, accountAction, deleteAccount, setStrategy, testConnection, refreshQuota, checkinNow, updateCheckin, toggleModel, setAllModels, updateEffort, refreshCatalog, saveContextWindow, resetContextWindow, resetAllContextWindows, updateContextDraft } = actions;
5836
- const t = zh$4;
5869
+ const t = zh$5;
5837
5870
  if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5838
5871
  className: "dsha-page",
5839
5872
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -6250,17 +6283,17 @@ window.__ModuleLoader__.load({
6250
6283
  * The names stay as they were so the hook that consumes them does not have to
6251
6284
  * change with the reader.
6252
6285
  */
6253
- const api$7 = createLineApi(MINIMAX_CODE_ROUTE_PREFIX, "MiniMax Code");
6254
- api$7.request;
6255
- const get = api$7.get;
6256
- const post$1 = api$7.post;
6257
- function messageOf(cause) {
6286
+ const api$8 = createLineApi(MINIMAX_CODE_ROUTE_PREFIX, "MiniMax Code");
6287
+ api$8.request;
6288
+ const get$1 = api$8.get;
6289
+ const post$2 = api$8.post;
6290
+ function messageOf$1(cause) {
6258
6291
  return cause instanceof Error ? cause.message : String(cause);
6259
6292
  }
6260
6293
  //#endregion
6261
6294
  //#region src/client/minimax-code/locales.ts
6262
6295
  const NS_MINIMAX_CODE = "dsh-minimax-code";
6263
- const zh$3 = {
6296
+ const zh$4 = {
6264
6297
  ...accountPoolZh,
6265
6298
  title: "MiniMax Code",
6266
6299
  pageDesc: "登录 MiniMax Code 编程订阅(设备码 OAuth),复用本机 MiniMax Code 的登录态,管理账号、连接与模型。",
@@ -6350,7 +6383,7 @@ window.__ModuleLoader__.load({
6350
6383
  loading: "加载中...",
6351
6384
  unknown: "—"
6352
6385
  };
6353
- const en$3 = {
6386
+ const en$4 = {
6354
6387
  ...accountPoolEn,
6355
6388
  title: "MiniMax Code",
6356
6389
  pageDesc: "Sign in to the MiniMax Code coding subscription (device-code OAuth) and reuse the local MiniMax Code sign-in to manage the account, connection, and models.",
@@ -6440,11 +6473,11 @@ window.__ModuleLoader__.load({
6440
6473
  loading: "Loading...",
6441
6474
  unknown: "—"
6442
6475
  };
6443
- const dictionaries$3 = {
6444
- zh: zh$3,
6445
- "zh-CN": zh$3,
6446
- en: en$3,
6447
- "en-US": en$3
6476
+ const dictionaries$4 = {
6477
+ zh: zh$4,
6478
+ "zh-CN": zh$4,
6479
+ en: en$4,
6480
+ "en-US": en$4
6448
6481
  };
6449
6482
  //#endregion
6450
6483
  //#region src/client/minimax-code/useMinimaxCodeSection.ts
@@ -6458,7 +6491,7 @@ window.__ModuleLoader__.load({
6458
6491
  * rather than inferred from the JSX.
6459
6492
  */
6460
6493
  /** The card's own dictionary; stable identity keeps effect dependencies intact. */
6461
- const fallbackTranslate = (key) => zh$3[key];
6494
+ const fallbackTranslate$1 = (key) => zh$4[key];
6462
6495
  /**
6463
6496
  * The shared pool card's labels, resolved through this card's dictionary.
6464
6497
  *
@@ -6469,7 +6502,7 @@ window.__ModuleLoader__.load({
6469
6502
  * shared card cannot be silently missed — the `satisfies` below turns that into a
6470
6503
  * compile error.
6471
6504
  */
6472
- function accountPoolLabelsFor(t) {
6505
+ function accountPoolLabelsFor$1(t) {
6473
6506
  return {
6474
6507
  accountPool: t("accountPool"),
6475
6508
  addAccount: t("addAccount"),
@@ -6504,9 +6537,9 @@ window.__ModuleLoader__.load({
6504
6537
  };
6505
6538
  }
6506
6539
  /** Device-code poll cadence. The host owns the real expiry. */
6507
- const LOGIN_POLL_INTERVAL_MS = 2e3;
6540
+ const LOGIN_POLL_INTERVAL_MS$1 = 2e3;
6508
6541
  function useMinimaxCodeSection({ onModelChange }) {
6509
- const t = fallbackTranslate;
6542
+ const t = fallbackTranslate$1;
6510
6543
  const [status, setStatus] = (0, react.useState)(null);
6511
6544
  const [loading, setLoading] = (0, react.useState)(true);
6512
6545
  const [busy, setBusy] = (0, react.useState)(null);
@@ -6521,7 +6554,7 @@ window.__ModuleLoader__.load({
6521
6554
  const loadStatus = (0, react.useCallback)(async (quiet = false) => {
6522
6555
  if (!quiet) setError(null);
6523
6556
  try {
6524
- const next = await get("/status");
6557
+ const next = await get$1("/status");
6525
6558
  setStatus(next);
6526
6559
  setContextDrafts(contextDraftsFor(next));
6527
6560
  quotaFollowUp.current ??= createQuotaFollowUp();
@@ -6529,7 +6562,7 @@ window.__ModuleLoader__.load({
6529
6562
  loadStatus(true);
6530
6563
  });
6531
6564
  } catch (cause) {
6532
- if (!quiet) setError(messageOf(cause));
6565
+ if (!quiet) setError(messageOf$1(cause));
6533
6566
  } finally {
6534
6567
  setLoading(false);
6535
6568
  }
@@ -6558,7 +6591,7 @@ window.__ModuleLoader__.load({
6558
6591
  const timer = window.setInterval(() => {
6559
6592
  (async () => {
6560
6593
  try {
6561
- const poll = await post$1("/login/poll", { loginId });
6594
+ const poll = await post$2("/login/poll", { loginId });
6562
6595
  if (stopped || poll.status === "pending") return;
6563
6596
  stopped = true;
6564
6597
  window.clearInterval(timer);
@@ -6571,7 +6604,7 @@ window.__ModuleLoader__.load({
6571
6604
  setError(poll.status === "expired" ? t("loginExpired") : t("loginDenied"));
6572
6605
  } catch {}
6573
6606
  })();
6574
- }, LOGIN_POLL_INTERVAL_MS);
6607
+ }, LOGIN_POLL_INTERVAL_MS$1);
6575
6608
  return () => {
6576
6609
  stopped = true;
6577
6610
  window.clearInterval(timer);
@@ -6599,7 +6632,7 @@ window.__ModuleLoader__.load({
6599
6632
  quotaRequested.current = true;
6600
6633
  (async () => {
6601
6634
  try {
6602
- setStatus(await post$1("/quota"));
6635
+ setStatus(await post$2("/quota"));
6603
6636
  } catch {}
6604
6637
  })();
6605
6638
  }, [authenticated, status?.quota]);
@@ -6609,7 +6642,7 @@ window.__ModuleLoader__.load({
6609
6642
  setError(null);
6610
6643
  setConnectionNotice(null);
6611
6644
  setCopied(false);
6612
- const started = await post$1("/login/start");
6645
+ const started = await post$2("/login/start");
6613
6646
  const next = started.login ?? (typeof started.loginId === "string" ? started : void 0);
6614
6647
  if (next === void 0) {
6615
6648
  setError(t("loginFailed"));
@@ -6617,7 +6650,7 @@ window.__ModuleLoader__.load({
6617
6650
  }
6618
6651
  setFlow(next);
6619
6652
  } catch (cause) {
6620
- setError(messageOf(cause));
6653
+ setError(messageOf$1(cause));
6621
6654
  } finally {
6622
6655
  setBusy(null);
6623
6656
  }
@@ -6627,9 +6660,9 @@ window.__ModuleLoader__.load({
6627
6660
  setFlow(null);
6628
6661
  if (pending === null) return;
6629
6662
  try {
6630
- await post$1("/login/cancel", { loginId: pending.loginId });
6663
+ await post$2("/login/cancel", { loginId: pending.loginId });
6631
6664
  } catch (cause) {
6632
- setError(messageOf(cause));
6665
+ setError(messageOf$1(cause));
6633
6666
  }
6634
6667
  };
6635
6668
  const copyCode = async () => {
@@ -6647,12 +6680,12 @@ window.__ModuleLoader__.load({
6647
6680
  setError(null);
6648
6681
  setConnectionNotice(null);
6649
6682
  setFlow(null);
6650
- const result = await post$1("/logout");
6683
+ const result = await post$2("/logout");
6651
6684
  if (result.native === true) setConnectionNotice(result.error ?? t("logoutOwnedByApp"));
6652
6685
  await loadStatus(true);
6653
6686
  onModelChange?.();
6654
6687
  } catch (cause) {
6655
- setError(messageOf(cause));
6688
+ setError(messageOf$1(cause));
6656
6689
  await loadStatus(true);
6657
6690
  } finally {
6658
6691
  setBusy(null);
@@ -6667,7 +6700,7 @@ window.__ModuleLoader__.load({
6667
6700
  /** Re-read the pool slice, which lives beside the status on its own route. */
6668
6701
  const loadPool = (0, react.useCallback)(async () => {
6669
6702
  try {
6670
- const next = await get("/accounts");
6703
+ const next = await get$1("/accounts");
6671
6704
  setPool(next);
6672
6705
  } catch {
6673
6706
  setPool(void 0);
@@ -6678,7 +6711,7 @@ window.__ModuleLoader__.load({
6678
6711
  try {
6679
6712
  setBusy(action);
6680
6713
  setError(null);
6681
- await post$1("/accounts", {
6714
+ await post$2("/accounts", {
6682
6715
  action,
6683
6716
  accountId
6684
6717
  });
@@ -6686,7 +6719,7 @@ window.__ModuleLoader__.load({
6686
6719
  await loadStatus(true);
6687
6720
  onModelChange?.();
6688
6721
  } catch (cause) {
6689
- setError(messageOf(cause));
6722
+ setError(messageOf$1(cause));
6690
6723
  } finally {
6691
6724
  setBusy(null);
6692
6725
  }
@@ -6695,13 +6728,13 @@ window.__ModuleLoader__.load({
6695
6728
  try {
6696
6729
  setBusy("strategy");
6697
6730
  setError(null);
6698
- await post$1("/accounts", {
6731
+ await post$2("/accounts", {
6699
6732
  action: "strategy",
6700
6733
  strategy
6701
6734
  });
6702
6735
  await loadPool();
6703
6736
  } catch (cause) {
6704
- setError(messageOf(cause));
6737
+ setError(messageOf$1(cause));
6705
6738
  } finally {
6706
6739
  setBusy(null);
6707
6740
  }
@@ -6709,12 +6742,12 @@ window.__ModuleLoader__.load({
6709
6742
  const applyEnabled = async (enabledModelIds) => {
6710
6743
  try {
6711
6744
  setError(null);
6712
- const updated = await post$1("/models", { enabledModelIds });
6745
+ const updated = await post$2("/models", { enabledModelIds });
6713
6746
  setStatus(updated);
6714
6747
  setContextDrafts(contextDraftsFor(updated));
6715
6748
  onModelChange?.();
6716
6749
  } catch (cause) {
6717
- setError(messageOf(cause));
6750
+ setError(messageOf$1(cause));
6718
6751
  }
6719
6752
  };
6720
6753
  /** Flip the check-in scheduler's own switch, through the same settings route. */
@@ -6722,10 +6755,10 @@ window.__ModuleLoader__.load({
6722
6755
  try {
6723
6756
  setBusy("checkin");
6724
6757
  setError(null);
6725
- const updated = await post$1("/settings", { checkin: { enabled } });
6758
+ const updated = await post$2("/settings", { checkin: { enabled } });
6726
6759
  setStatus(updated);
6727
6760
  } catch (cause) {
6728
- setError(messageOf(cause));
6761
+ setError(messageOf$1(cause));
6729
6762
  } finally {
6730
6763
  setBusy(null);
6731
6764
  }
@@ -6735,10 +6768,10 @@ window.__ModuleLoader__.load({
6735
6768
  try {
6736
6769
  setBusy("checkin");
6737
6770
  setError(null);
6738
- const updated = await post$1("/checkin/now");
6771
+ const updated = await post$2("/checkin/now");
6739
6772
  setStatus(updated);
6740
6773
  } catch (cause) {
6741
- setError(messageOf(cause));
6774
+ setError(messageOf$1(cause));
6742
6775
  } finally {
6743
6776
  setBusy(null);
6744
6777
  }
@@ -6756,11 +6789,11 @@ window.__ModuleLoader__.load({
6756
6789
  const updateEffort = async (effort) => {
6757
6790
  try {
6758
6791
  setError(null);
6759
- const updated = await post$1("/settings", { defaultReasoningEffort: effort });
6792
+ const updated = await post$2("/settings", { defaultReasoningEffort: effort });
6760
6793
  setStatus(updated);
6761
6794
  onModelChange?.();
6762
6795
  } catch (cause) {
6763
- setError(messageOf(cause));
6796
+ setError(messageOf$1(cause));
6764
6797
  }
6765
6798
  };
6766
6799
  const saveContextWindow = async (modelId) => {
@@ -6773,7 +6806,7 @@ window.__ModuleLoader__.load({
6773
6806
  try {
6774
6807
  setSavingModel(modelId);
6775
6808
  setError(null);
6776
- const updated = await post$1("/settings", { contextWindowOverrides: { [modelId]: parsed } });
6809
+ const updated = await post$2("/settings", { contextWindowOverrides: { [modelId]: parsed } });
6777
6810
  setStatus(updated);
6778
6811
  setContextDrafts((prev) => ({
6779
6812
  ...prev,
@@ -6781,7 +6814,7 @@ window.__ModuleLoader__.load({
6781
6814
  }));
6782
6815
  onModelChange?.();
6783
6816
  } catch (cause) {
6784
- setError(messageOf(cause));
6817
+ setError(messageOf$1(cause));
6785
6818
  } finally {
6786
6819
  setSavingModel(null);
6787
6820
  }
@@ -6790,7 +6823,7 @@ window.__ModuleLoader__.load({
6790
6823
  try {
6791
6824
  setSavingModel(modelId);
6792
6825
  setError(null);
6793
- const updated = await post$1("/settings", { contextWindowOverrides: { [modelId]: null } });
6826
+ const updated = await post$2("/settings", { contextWindowOverrides: { [modelId]: null } });
6794
6827
  setStatus(updated);
6795
6828
  const model = updated.models.find((entry) => entry.id === modelId);
6796
6829
  if (model !== void 0) setContextDrafts((prev) => ({
@@ -6799,7 +6832,7 @@ window.__ModuleLoader__.load({
6799
6832
  }));
6800
6833
  onModelChange?.();
6801
6834
  } catch (cause) {
6802
- setError(messageOf(cause));
6835
+ setError(messageOf$1(cause));
6803
6836
  } finally {
6804
6837
  setSavingModel(null);
6805
6838
  }
@@ -6809,12 +6842,12 @@ window.__ModuleLoader__.load({
6809
6842
  if (ids.length === 0) return;
6810
6843
  try {
6811
6844
  setError(null);
6812
- const updated = await post$1("/settings", { contextWindowOverrides: Object.fromEntries(ids.map((id) => [id, null])) });
6845
+ const updated = await post$2("/settings", { contextWindowOverrides: Object.fromEntries(ids.map((id) => [id, null])) });
6813
6846
  setStatus(updated);
6814
6847
  setContextDrafts(contextDraftsFor(updated));
6815
6848
  onModelChange?.();
6816
6849
  } catch (cause) {
6817
- setError(messageOf(cause));
6850
+ setError(messageOf$1(cause));
6818
6851
  }
6819
6852
  };
6820
6853
  /** Force one usage read through `/quota` and render the fresh status. */
@@ -6822,9 +6855,9 @@ window.__ModuleLoader__.load({
6822
6855
  try {
6823
6856
  setBusy("quota");
6824
6857
  setError(null);
6825
- setStatus(await post$1("/quota"));
6858
+ setStatus(await post$2("/quota"));
6826
6859
  } catch (cause) {
6827
- setError(messageOf(cause));
6860
+ setError(messageOf$1(cause));
6828
6861
  } finally {
6829
6862
  setBusy(null);
6830
6863
  }
@@ -6834,14 +6867,14 @@ window.__ModuleLoader__.load({
6834
6867
  setBusy("test");
6835
6868
  setError(null);
6836
6869
  setConnectionNotice(null);
6837
- const result = await post$1("/test");
6870
+ const result = await post$2("/test");
6838
6871
  if (result.ok === true) {
6839
6872
  setConnectionNotice(result.model === void 0 || result.model === "" ? t("testSuccess") : t("testSuccessModel").replace("{model}", result.model));
6840
6873
  return;
6841
6874
  }
6842
6875
  setConnectionNotice(result.error === void 0 || result.error === "" ? t("testFailed") : `${t("testFailed")}:${result.error}`);
6843
6876
  } catch (cause) {
6844
- setConnectionNotice(`${t("testFailed")}:${messageOf(cause)}`);
6877
+ setConnectionNotice(`${t("testFailed")}:${messageOf$1(cause)}`);
6845
6878
  } finally {
6846
6879
  setBusy(null);
6847
6880
  }
@@ -6877,7 +6910,7 @@ window.__ModuleLoader__.load({
6877
6910
  models,
6878
6911
  contextModels,
6879
6912
  overrideCount,
6880
- poolLabels: accountPoolLabelsFor(t)
6913
+ poolLabels: accountPoolLabelsFor$1(t)
6881
6914
  },
6882
6915
  actions: {
6883
6916
  login,
@@ -6934,7 +6967,7 @@ window.__ModuleLoader__.load({
6934
6967
  const { status, loading, busy, error, flow, copied, connectionNotice, contextDrafts, savingModel, pool } = state;
6935
6968
  const { authenticated, account, quota, models, contextModels, overrideCount, poolLabels } = derived;
6936
6969
  const { login, cancelLogin, copyCode, logout, poolAction, setStrategy, toggleModel, setAllModels, setCheckinEnabled, runCheckinNow, updateEffort, saveContextWindow, resetContextWindow, resetAllContextWindows, refreshQuota, testConnection, updateContextDraft } = actions;
6937
- const t = fallbackTranslate;
6970
+ const t = fallbackTranslate$1;
6938
6971
  if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6939
6972
  className: "dsha-page",
6940
6973
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -7325,79 +7358,1227 @@ window.__ModuleLoader__.load({
7325
7358
  });
7326
7359
  }
7327
7360
  //#endregion
7328
- //#region src/shared/claude-contracts.ts
7329
- /**
7330
- * Every thinking level this route can name, in escalating order.
7331
- *
7332
- * The union of the whole shipped catalog rather than one model's ladder: these
7333
- * are WIRE effort values, already collapsed by the upstream reference mapping
7334
- * the frozen catalog transcribes ('minimal' and 'low' both send 'low', so
7335
- * offering both would advertise a distinction the wire cannot make). The card
7336
- * offers them as default-effort choices and narrows the dropdown per model with
7337
- * {@link ClaudeModelOption.reasoningEfforts}.
7338
- *
7339
- * 'off' is deliberately absent, exactly as it is from every ladder in the
7340
- * catalog: turning thinking off is the ABSENCE of a thinking block rather than
7341
- * an effort level, and whether a model permits it is stated separately in
7342
- * {@link ClaudeModelOption.canDisableThinking}.
7343
- *
7344
- * NOT derived from the catalog by an indexed access — the client project cannot
7345
- * read that module. The equivalence is asserted against the real table in
7346
- * 'src/host/claude/routes.ts'; see the module comment.
7347
- */
7348
- const CLAUDE_REASONING_EFFORTS = [
7349
- "low",
7350
- "medium",
7351
- "high",
7352
- "xhigh",
7353
- "max"
7354
- ];
7355
- //#endregion
7356
- //#region src/client/claude/locales.ts
7361
+ //#region src/client/glm-coding-plan/locales.ts
7357
7362
  /**
7358
- * Locale namespace of the Claude subscription tab.
7363
+ * GLM(ZCode 账号)线路的客户端命名空间。
7359
7364
  *
7360
- * Its own namespace rather than the hub's, so a missing string surfaces as this
7361
- * dictionary's key rather than as a wrong sentence borrowed from another
7362
- * provider — the same reason every sibling line has one.
7365
+ * 与其余每条线路一个命名空间:卡片渲染自己的字典,不复用 hub 挂在
7366
+ * `settings.section` 上的那张座位(那张座绑定的是 ChatGPT 的键集,
7367
+ * 键名重合的会被渲染成 ChatGPT 的措辞,不重合的会把键名本身打印出来)。
7363
7368
  */
7364
- const NS_CLAUDE = "dsh-claude";
7365
- const zh$2 = {
7369
+ const NS_GLM_CODING_PLAN = "dsh-glm-coding-plan";
7370
+ const zh$3 = {
7366
7371
  ...accountPoolZh,
7367
- title: "Claude(订阅)",
7368
- pageDesc: "登录 Claude Pro/Max 订阅,管理模型、思考档位、上下文窗口与额度。",
7369
- account: "账号",
7370
- signedIn: "已登录",
7371
- signedOut: "未登录",
7372
- email: "邮箱",
7373
- plan: "套餐",
7374
- planUnknown: "—",
7375
- subscriptionType: "订阅类型",
7376
- source: "来源",
7377
- sourceManaged: "本插件登录",
7378
- sourceClaudeCode: "本机 Claude Code",
7379
- adoptedBadge: "导入的快照",
7380
- signIn: "登录 Claude 账号",
7381
- signInSection: "登录授权",
7382
- signInAgain: "重新登录",
7383
- signingIn: "正在发起登录...",
7384
- cancelSignIn: "取消登录",
7372
+ title: "GLM(ZCode 账号)",
7373
+ pageDesc: "用 ZCode 账号授权接入 GLM Coding Plan(国区 bigmodel.cn / 国际区 z.ai),管理账号池、套餐额度与模型勾选。两个区域的凭据各自独立,池内可以同时存在两区账号。",
7374
+ loading: "加载中...",
7375
+ region: "区域",
7376
+ regionCn: "国区(bigmodel.cn)",
7377
+ regionIntl: "国际区(z.ai)",
7378
+ regionHint: "「导入本机登录态」与「手工粘贴授权码」按这里选定的区域发起;上方两个登录按钮各自固定一个区域。区域是凭据的属性,一区铸造的 Key 会被另一区拒绝,所以两区账号互不串用。",
7379
+ addCnAccount: "添加国区账号",
7380
+ addIntlAccount: "添加国际区账号",
7381
+ authorizing: "授权中…",
7382
+ loginSection: "登录授权",
7383
+ loginIdle: "尚未开始登录。",
7384
+ loginPending: "等待浏览器完成登录与授权,然后本卡片会自动继续。",
7385
+ loginComplete: "登录完成,账号已加入号池。",
7386
+ loginCompletedAt: "完成时间:{time}",
7387
+ loginCompleteNoAccount: "这次登录完成了,但号池里已经没有这个账号(可能已被删除)。",
7388
+ loginError: "登录失败。",
7389
+ loginRetryable: "这是可重试的失败,可以直接重新发起一次登录。",
7390
+ loginNotRetryable: "这次失败不会自己好:请检查区域是否选对、网络是否可达,然后重新发起登录。",
7391
+ authorizeUrl: "授权页面",
7385
7392
  openAuthorizeUrl: "打开授权页面",
7386
- authorizeUrl: "授权链接",
7387
- redirectUri: "回调地址",
7388
- loginModeManual: "当前是手动模式:浏览器回调不可用,授权完成后把页面上的 code 粘贴到下方输入框。",
7389
- loginModeLoopback: "当前是本地回环模式:浏览器授权完成后会自动回到本机回调地址。",
7390
- loginFallbackReason: "本地回环模式不可用,已降级为手动模式:{detail}",
7391
- loginWaiting: "等待浏览器中的授权完成...",
7392
- loginExchanging: "正在交换令牌...",
7393
- loginComplete: "登录完成",
7394
- loginFailed: "登录失败",
7395
- manualPasteSection: "手动粘贴授权码",
7396
- manualPasteHint: "把浏览器地址栏里的 code(或整段回调 URL)粘贴到这里完成登录。手动模式下没有浏览器回调,这里是唯一的入口。",
7397
- manualPastePlaceholder: "code#state 或完整的回调 URL",
7393
+ pollEvery: "每 {seconds} 秒查询一次登录结果。",
7394
+ loginExpiresAt: "本次授权最长可用到 {time},过期后需要重新发起。",
7395
+ progress: "进度",
7396
+ restartLogin: "重新发起登录",
7397
+ cancelLogin: "取消登录",
7398
+ cancelLoginBusy: "取消中…",
7399
+ manualPasteSection: "手工粘贴授权码",
7400
+ manualPasteHint: "浏览器回调被拦截、或授权页拿不到 code 时,把 ZCode 回调里的授权码粘贴到下面即可完成兑换——这条兜底通道是回调走不通时唯一能完成登录的地方,所以它一直在,只是没有进行中的流程时默认收起,流程一开始(进行中或失败)就自动展开。",
7401
+ manualPastePlaceholder: "粘贴授权码(code=… 或整段回调地址)",
7398
7402
  manualPasteSubmit: "提交授权码",
7399
- manualPasteSubmitting: "提交中...",
7400
- importClaudeCode: "导入本机 Claude Code 登录态",
7403
+ manualPasteSubmitting: "兑换中…",
7404
+ manualPasteEmpty: "请先粘贴授权码。",
7405
+ adopt: "导入本机 ZCode 登录态",
7406
+ adopting: "导入中…",
7407
+ adoptAdopted: "已导入本机 ZCode 的登录态({region}),无需重新登录。",
7408
+ adoptNoAttempt: "本机没有可导入的 ZCode 登录态。",
7409
+ adoptNoCredentialsFile: "没有找到 ZCode 的凭据文件(默认 ~/.zcode/v2/credentials.json)。装过 ZCode 客户端并登录过一次才会有这个文件。",
7410
+ adoptSecretUnavailable: "找到了凭据文件,但本机设置了 ZCODE_CREDENTIAL_SECRET,本插件无法推导解密密钥,因此读不出里面的登录态。",
7411
+ adoptDecryptFailed: "凭据解密失败,文件可能已被改动或损坏。",
7412
+ adoptTokenExpired: "ZCode 的登录态已经过期,回 ZCode 客户端重新登录后再导入。",
7413
+ adoptExchangeFailed: "兑换 Coding Plan Key 失败:这个账号可能没有 Coding Plan 套餐,或没有建 Key 的权限。",
7414
+ adoptNotAZcodeLogin: "凭据文件里没有本线路认识的 ZCode 登录态(该文件也可能属于别的工具)。",
7415
+ adoptFallback: "导入只是省一次登录的快捷路径,失败不影响使用——请改用上方的浏览器登录。",
7416
+ adoptedBadge: "导入的登录态",
7417
+ connection: "连接",
7418
+ testConnection: "测试连接",
7419
+ testingConnection: "测试中...",
7420
+ testSuccess: "连通正常",
7421
+ testSuccessAccount: "连通正常(账号 {account})",
7422
+ testSuccessModel: "连通正常({model})",
7423
+ testFailed: "连接测试失败",
7424
+ testFailedDetail: "连接测试失败:{detail}",
7425
+ testLatency: "往返 {ms} 毫秒",
7426
+ routeOwned: "本插件正在服务该模型路由。",
7427
+ routeConflict: "模型路由已被其他 Provider 占用:{detail}。请在 DSH 设置中移除重复的 Provider 配置后重新加载。",
7428
+ modelsSection: "模型",
7429
+ modelsHint: "勾选后模型才会出现在对话页的模型选择列表中;目录与能力说明来自本线路的随包目录,**不从模型名推断**(glm-5.3 与 glm-5.3-flash 的图片输入、glm-5.2 与 glm-5.3 的思考档位都不同)。目录按账号所在区域过滤,跨区调用会被上游拒绝。",
7430
+ modelsUnavailable: "暂无可显示的模型。",
7431
+ refreshCatalog: "刷新模型目录",
7432
+ refreshingCatalog: "刷新中...",
7433
+ dismiss: "知道了",
7434
+ selectAll: "全选",
7435
+ unselectAll: "全不选",
7436
+ modelChecklistCount: "{count}/{total}",
7437
+ contextWindowSection: "模型上下文窗口",
7438
+ contextWindowHint: "默认值来自随包目录(每个模型的真实上下文上限);可覆盖为自定义容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
7439
+ contextWindowNoneEnabled: "还没有勾选任何模型。在上方勾选后,这里会出现该模型的上下文窗口设置。",
7440
+ contextWindowReset: "恢复默认",
7441
+ contextWindowResetAll: "全部恢复默认",
7442
+ tokens: "tokens",
7443
+ save: "保存",
7444
+ saving: "保存中...",
7445
+ saved: "已保存",
7446
+ invalidCapacity: "容量格式无效:{value}",
7447
+ quotaSection: "用量与配额",
7448
+ quotaDesc: "数据来自 Coding Plan 的配额接口(该接口用裸 Key 鉴权,不加 Bearer)。",
7449
+ quotaRefresh: "刷新用量",
7450
+ quotaRefreshing: "刷新中...",
7451
+ quotaSignedOut: "未登录,先在上方完成登录授权。",
7452
+ quotaEmpty: "暂无配额数据,点击「刷新用量」重试。",
7453
+ quotaPlan: "套餐",
7454
+ quotaPlanLevel: "档位",
7455
+ quotaRenews: "续费时间",
7456
+ quotaReadAt: "读取时间",
7457
+ quotaSources: "数据源",
7458
+ quotaWindowNames: "窗口名按窗口长度本地化(5 小时 / 1 周 / 1 月),不在本页硬编码;每个账号自己的进度条画在它的账号卡片里。",
7459
+ quotaRefreshingNote: "正在后台刷新配额,下方是上一次读到的数字。",
7460
+ quotaErrorLabel: "配额读取失败",
7461
+ quotaAllowance: "额度类型",
7462
+ quotaAllowancePlan: "付费套餐",
7463
+ quotaAllowanceFreeTrial: "免费体验额度",
7464
+ quotaAllowanceUnknown: "未判定",
7465
+ quotaAllowanceHint: "登录时探活认定的额度来源。「免费体验额度」按官方文档指新用户注册即自动获得、首次使用起 5 天内每天 800 万 token 的体验额度;额度耗尽时由上游返回 429,本线路不预判。"
7466
+ };
7467
+ const en$3 = {
7468
+ ...accountPoolEn,
7469
+ title: "GLM (ZCode account)",
7470
+ pageDesc: "Sign in with a ZCode account to reach GLM Coding Plan (China bigmodel.cn / International z.ai), and manage the account pool, plan quota and model selection. The two regions hold independent credentials, so a pool can carry accounts from both.",
7471
+ loading: "Loading...",
7472
+ region: "Region",
7473
+ regionCn: "China (bigmodel.cn)",
7474
+ regionIntl: "International (z.ai)",
7475
+ regionHint: "“Import the local sign-in” and the manual code paste start on the region chosen here; the two sign-in buttons above each pin one region. A region is a property of the credential — a key minted in one region is refused by the other — so the two never share.",
7476
+ addCnAccount: "Add China account",
7477
+ addIntlAccount: "Add international account",
7478
+ authorizing: "Authorizing…",
7479
+ loginSection: "Sign-in",
7480
+ loginIdle: "No sign-in started yet.",
7481
+ loginPending: "Finish sign-in and authorization in the browser; this card then continues on its own.",
7482
+ loginComplete: "Signed in — the account joined the pool.",
7483
+ loginCompletedAt: "Signed in at {time}",
7484
+ loginCompleteNoAccount: "That sign-in completed, but the account is no longer in the pool (it may have been deleted).",
7485
+ loginError: "Sign-in failed.",
7486
+ loginRetryable: "This failure is retryable: start a fresh sign-in.",
7487
+ loginNotRetryable: "This failure will not resolve itself: check that the region is right and the network is reachable, then start again.",
7488
+ authorizeUrl: "Authorization page",
7489
+ openAuthorizeUrl: "Open the authorization page",
7490
+ pollEvery: "Polling for the result every {seconds}s.",
7491
+ loginExpiresAt: "This authorization is valid until {time}; after that a new one must be started.",
7492
+ progress: "Progress",
7493
+ restartLogin: "Start again",
7494
+ cancelLogin: "Cancel sign-in",
7495
+ cancelLoginBusy: "Cancelling…",
7496
+ manualPasteSection: "Paste the code by hand",
7497
+ manualPasteHint: "When the browser callback is blocked or the page never yields a code, paste the authorization code from the ZCode callback below and the exchange finishes — this fallback is the only way a blocked sign-in can still finish, so it is always here: collapsed while no flow is running, expanded on its own once one starts (pending or failed).",
7498
+ manualPastePlaceholder: "Paste the code (code=… or the whole callback URL)",
7499
+ manualPasteSubmit: "Submit the code",
7500
+ manualPasteSubmitting: "Exchanging…",
7501
+ manualPasteEmpty: "Paste a code first.",
7502
+ adopt: "Import the local ZCode sign-in",
7503
+ adopting: "Importing…",
7504
+ adoptAdopted: "Imported the local ZCode sign-in ({region}); no sign-in needed.",
7505
+ adoptNoAttempt: "There is no local ZCode sign-in to import.",
7506
+ adoptNoCredentialsFile: "No ZCode credentials file found (by default ~/.zcode/v2/credentials.json). It exists once the ZCode client has been installed and signed into.",
7507
+ adoptSecretUnavailable: "The credentials file exists, but this machine sets ZCODE_CREDENTIAL_SECRET, so the decryption key cannot be derived and the sign-in inside it cannot be read.",
7508
+ adoptDecryptFailed: "Decryption failed; the file may have been edited or damaged.",
7509
+ adoptTokenExpired: "The ZCode sign-in has expired — sign in again in the ZCode client and import once more.",
7510
+ adoptExchangeFailed: "Exchanging the Coding Plan key failed: this account may have no Coding Plan, or no permission to create a key.",
7511
+ adoptNotAZcodeLogin: "The credentials file holds no ZCode sign-in this line recognizes (it may belong to another tool).",
7512
+ adoptFallback: "Importing only saves you one sign-in; a failure never blocks the line — use the browser sign-in above instead.",
7513
+ adoptedBadge: "Imported sign-in",
7514
+ connection: "Connection",
7515
+ testConnection: "Test connection",
7516
+ testingConnection: "Testing...",
7517
+ testSuccess: "Connection OK",
7518
+ testSuccessAccount: "Connection OK (account {account})",
7519
+ testSuccessModel: "Connection OK ({model})",
7520
+ testFailed: "Connection test failed",
7521
+ testFailedDetail: "Connection test failed: {detail}",
7522
+ testLatency: "{ms} ms round trip",
7523
+ routeOwned: "This plugin serves the model route.",
7524
+ routeConflict: "Another provider already owns the model route: {detail}. Remove the duplicate provider configuration in DSH settings and reload.",
7525
+ modelsSection: "Models",
7526
+ modelsHint: "Only checked models appear in the conversation model picker. The catalog and every capability sentence come from this line's bundled directory and are never inferred from a model name (GLM-5.3 and GLM-5.3-Flash differ in image input, GLM-5.2 and GLM-5.3 in thinking levels). The catalog is filtered by the account's region; the upstream rejects a model asked of the wrong region.",
7527
+ modelsUnavailable: "No model to show yet.",
7528
+ refreshCatalog: "Refresh catalog",
7529
+ refreshingCatalog: "Refreshing...",
7530
+ dismiss: "Dismiss",
7531
+ selectAll: "Select all",
7532
+ unselectAll: "Deselect all",
7533
+ modelChecklistCount: "{count}/{total}",
7534
+ contextWindowSection: "Model context windows",
7535
+ contextWindowHint: "Defaults come from the bundled directory (each model's real context cap). Override one with the capacity DSH should use for compaction and overflow decisions; 1M, 512K, 200K and similar are accepted.",
7536
+ contextWindowNoneEnabled: "No model is checked yet. Check one above and its context window setting appears here.",
7537
+ contextWindowReset: "Restore default",
7538
+ contextWindowResetAll: "Restore all defaults",
7539
+ tokens: "tokens",
7540
+ save: "Save",
7541
+ saving: "Saving...",
7542
+ saved: "Saved",
7543
+ invalidCapacity: "Invalid capacity: {value}",
7544
+ quotaSection: "Usage & quota",
7545
+ quotaDesc: "Read from the Coding Plan quota endpoint, which authenticates with the bare key and no Bearer prefix.",
7546
+ quotaRefresh: "Refresh usage",
7547
+ quotaRefreshing: "Refreshing...",
7548
+ quotaSignedOut: "Not signed in — finish the sign-in above first.",
7549
+ quotaEmpty: "No quota data yet — use “Refresh usage” to retry.",
7550
+ quotaPlan: "Plan",
7551
+ quotaPlanLevel: "Tier",
7552
+ quotaRenews: "Renews",
7553
+ quotaReadAt: "Read at",
7554
+ quotaSources: "Sources",
7555
+ quotaWindowNames: "Window names are localized from the window length (5 hours / 1 week / 1 month) rather than hardcoded here; each account's own progress bar is drawn on its account card.",
7556
+ quotaRefreshingNote: "Quota is refreshing in the background; the figures below are the last read.",
7557
+ quotaErrorLabel: "Quota read failed",
7558
+ quotaAllowance: "Allowance",
7559
+ quotaAllowancePlan: "Paid plan",
7560
+ quotaAllowanceFreeTrial: "Free trial allowance",
7561
+ quotaAllowanceUnknown: "Undetermined",
7562
+ quotaAllowanceHint: "The allowance source established by the sign-in probe. “Free trial allowance” is what official docs describe as 8M tokens per day for 5 days from first use, granted automatically to new accounts; once it runs out the upstream answers 429, which this line does not pre-empt."
7563
+ };
7564
+ const dictionaries$3 = {
7565
+ zh: zh$3,
7566
+ "zh-CN": zh$3,
7567
+ en: en$3,
7568
+ "en-US": en$3
7569
+ };
7570
+ /** 一个配额窗口的键到「窗口长度(分钟)」的映射。 */
7571
+ const QUOTA_WINDOW_MINUTES = {
7572
+ "five-hour": 300,
7573
+ weekly: 10080,
7574
+ monthly: 43200
7575
+ };
7576
+ /** reason → 字典键。一个 reason 一种文案,因此这里是封闭映射而不是兜底串。 */
7577
+ const ADOPT_REASON_KEYS = {
7578
+ "no-credentials-file": "adoptNoCredentialsFile",
7579
+ "secret-unavailable": "adoptSecretUnavailable",
7580
+ "decrypt-failed": "adoptDecryptFailed",
7581
+ "token-expired": "adoptTokenExpired",
7582
+ "exchange-failed": "adoptExchangeFailed",
7583
+ "not-a-zcode-login": "adoptNotAZcodeLogin"
7584
+ };
7585
+ function adoptReasonText(reason, dictionary) {
7586
+ return dictionary[ADOPT_REASON_KEYS[reason]];
7587
+ }
7588
+ /** 额度类型 → 字典键。三个取值各有各的话,刻意不做兜底串。 */
7589
+ const ALLOWANCE_KINDS = {
7590
+ plan: "quotaAllowancePlan",
7591
+ "free-trial": "quotaAllowanceFreeTrial",
7592
+ unknown: "quotaAllowanceUnknown"
7593
+ };
7594
+ /**
7595
+ * 额度类型的本地化文案。
7596
+ *
7597
+ * `undefined`(旧 host 没下发这个字段)与 `'unknown'` 都渲染成「未判定」:
7598
+ * 读不到就等于不知道,而「不知道」不能被渲染成付费套餐。
7599
+ */
7600
+ function allowanceKindText(allowance, dictionary) {
7601
+ return dictionary[ALLOWANCE_KINDS[allowance ?? "unknown"]];
7602
+ }
7603
+ //#endregion
7604
+ //#region src/client/glm-coding-plan/api.ts
7605
+ /**
7606
+ * 本线路的 host 路由由这一个文件描述,卡片与输入框胶囊都从这里取。
7607
+ *
7608
+ * **路由表是与 W6 的约定**:host 侧 src/host/glm-coding-plan/routes.ts 尚未交付,
7609
+ * 下表按计划 §6.1("/glm-coding-plan/api 全套")与兄弟线路的命名习惯定下,
7610
+ * 一旦 host 侧拼写不同,只需要改这一个文件。
7611
+ *
7612
+ * GET /status → GlmStatusDto(页面的唯一读口)
7613
+ * POST /settings GlmSettingsUpdateDto → GlmStatusDto(开关、模型勾选、上下文窗口、档位)
7614
+ * POST /accounts { action, accountId } / { action:'strategy', strategy } → GlmStatusDto
7615
+ * POST /login/start { region } → GlmLoginFlowStatus
7616
+ * GET /login/status → GlmLoginFlowStatus(浏览器授权不由卡片控制,卡片跟随 host)
7617
+ * POST /login/cancel → GlmLoginFlowStatus
7618
+ * POST /login/manual { region, code } → GlmStatusDto(手工粘贴兜底;请求体刻意不在冻结契约里)
7619
+ * POST /adopt { region } → GlmAdoptResultDto(失败永不阻断,卡片据 reason 给文案)
7620
+ * POST /connection/test → GlmConnectionDto
7621
+ * POST /quota → GlmStatusDto(强制刷新配额)
7622
+ * POST /catalog/refresh → GlmStatusDto
7623
+ *
7624
+ * 除 adopt 与 connection/test 外,全部走共享的 { ok, value } 信封,
7625
+ * 因此答案都是裸 DTO——createLineApi 已经把信封拆掉了。
7626
+ */
7627
+ const api$7 = createLineApi(GLM_CODING_PLAN_ROUTE_PREFIX, "GLM(ZCode 账号)");
7628
+ const get = api$7.get;
7629
+ const post$1 = api$7.post;
7630
+ function messageOf(cause) {
7631
+ return cause instanceof Error ? cause.message : String(cause);
7632
+ }
7633
+ //#endregion
7634
+ //#region src/client/glm-coding-plan/useGlmCodingPlanSection.ts
7635
+ /**
7636
+ * GLM(ZCode 账号)设置卡片的状态、副作用与动作。
7637
+ *
7638
+ * 与 WorkBuddy / MiniMax Code 同样的分工:这个文件是行为,GlmCodingPlanSection.tsx
7639
+ * 是渲染,两者之间只通过下面这一个具名结构交接,卡片因此保持「只画」的状态。
7640
+ *
7641
+ * 一条设计约束贯穿全文件:**能力与文案都不在本文件重算**。模型行的一句话描述来自
7642
+ * 契约里的 GlmModelOption.hint(host 由随包目录生成),配额窗口名由共享配额条按
7643
+ * windowDurationMins 本地化;客户端一旦自己推断能力,就等于把「能力不得从模型名推断」
7644
+ * 这条规则(计划 §7)重新打开。
7645
+ */
7646
+ /** 登录状态机的轮询节奏。真实超时与间隔由 host 拥有,卡片只是跟随。 */
7647
+ const LOGIN_POLL_INTERVAL_MS = 2e3;
7648
+ /** 本卡片的字典;身份稳定,依赖它的 effect 才不会每次渲染重建。 */
7649
+ const fallbackTranslate = (key) => zh$3[key];
7650
+ /**
7651
+ * 共享账号池卡片需要的标签集,按本卡片的字典逐键查出来。
7652
+ *
7653
+ * 从共享 ZH 标签对象自身的键推导,因此共享卡片新增一个标签而这里漏掉时
7654
+ * 是编译错误,而不是页面上少一句话。
7655
+ */
7656
+ function accountPoolLabelsFor(t) {
7657
+ return {
7658
+ accountPool: t("accountPool"),
7659
+ addAccount: t("addAccount"),
7660
+ accountCount: t("accountCount"),
7661
+ primaryAccount: t("primaryAccount"),
7662
+ activeAccount: t("activeAccount"),
7663
+ setPrimary: t("setPrimary"),
7664
+ deleteAccount: t("deleteAccount"),
7665
+ cooling: t("cooling"),
7666
+ cooldownLeft: t("cooldownLeft"),
7667
+ clearCooldown: t("clearCooldown"),
7668
+ needsRelogin: t("needsRelogin"),
7669
+ relogin: t("relogin"),
7670
+ rotationStrategy: t("rotationStrategy"),
7671
+ strategySequential: t("strategySequential"),
7672
+ strategyRoundRobin: t("strategyRoundRobin"),
7673
+ strategySticky: t("strategySticky"),
7674
+ noAccounts: t("noAccounts"),
7675
+ email: t("email"),
7676
+ expires: t("expires"),
7677
+ lastUsed: t("lastUsed"),
7678
+ accountId: t("accountId"),
7679
+ accountQuota: t("accountQuota"),
7680
+ quotaNone: t("quotaNone"),
7681
+ quotaSnapshot: t("quotaSnapshot"),
7682
+ quotaResets: t("quotaResets"),
7683
+ quotaExhausted: t("quotaExhausted"),
7684
+ quotaWindow: t("quotaWindow"),
7685
+ quotaUsed: t("quotaUsed"),
7686
+ quotaFactsScope: t("quotaFactsScope"),
7687
+ composerLabel: t("composerLabel")
7688
+ };
7689
+ }
7690
+ /**
7691
+ * host 下发的号池行 → 契约里带区域的那一行。
7692
+ *
7693
+ * 冻结契约写的是 `accounts?: PoolAccountSummaryDto[]`(GlmStatusDto 继承的是
7694
+ * Partial<AccountPoolStatusDto>),元素类型是最小的 PoolAccountSummaryDto,
7695
+ * GlmAccountSummaryDto 是它的**扩展**而不是它的元素类型;契约已冻结,所以这里在
7696
+ * 客户端补齐:region 等 host 确实下发的字段原样取,只有缺失时才回落到当前区域。
7697
+ */
7698
+ function glmAccounts(status) {
7699
+ const fallback = status?.region ?? "cn";
7700
+ return (status?.accounts ?? []).map((account) => {
7701
+ const extra = account;
7702
+ return {
7703
+ ...account,
7704
+ region: isGlmRegion(extra.region) ? extra.region : fallback,
7705
+ ...extra.organizationId === void 0 ? {} : { organizationId: extra.organizationId },
7706
+ ...extra.accountName === void 0 ? {} : { accountName: extra.accountName }
7707
+ };
7708
+ });
7709
+ }
7710
+ function useGlmCodingPlanSection({ onModelChange } = {}) {
7711
+ const t = fallbackTranslate;
7712
+ const [status, setStatus] = (0, react.useState)(null);
7713
+ const [loading, setLoading] = (0, react.useState)(true);
7714
+ const [busy, setBusy] = (0, react.useState)(null);
7715
+ const [error, setError] = (0, react.useState)(null);
7716
+ const [connection, setConnection] = (0, react.useState)(null);
7717
+ const [adoptResult, setAdoptResult] = (0, react.useState)(null);
7718
+ const [pasteValue, setPasteValue] = (0, react.useState)("");
7719
+ const [pasteOpen, setPasteOpen] = (0, react.useState)(false);
7720
+ const [region, setRegionState] = (0, react.useState)("cn");
7721
+ const [contextDrafts, setContextDrafts] = (0, react.useState)({});
7722
+ const [savingModel, setSavingModel] = (0, react.useState)(null);
7723
+ const regionTouched = (0, react.useRef)(false);
7724
+ const quotaFollowUp = (0, react.useRef)(void 0);
7725
+ const loadStatus = (0, react.useCallback)(async (quiet = false) => {
7726
+ if (!quiet) setError(null);
7727
+ try {
7728
+ const next = await get("/status");
7729
+ setStatus(next);
7730
+ setContextDrafts(contextDraftsFor(next));
7731
+ if (!regionTouched.current) setRegionState(next.region);
7732
+ quotaFollowUp.current ??= createQuotaFollowUp();
7733
+ quotaFollowUp.current.observe(next.quotaRefreshing === true, () => {
7734
+ loadStatus(true);
7735
+ });
7736
+ } catch (cause) {
7737
+ if (!quiet) setError(messageOf(cause));
7738
+ } finally {
7739
+ setLoading(false);
7740
+ }
7741
+ }, []);
7742
+ (0, react.useEffect)(() => {
7743
+ loadStatus();
7744
+ const refreshWhenVisible = () => {
7745
+ if (document.visibilityState === "visible") loadStatus(true);
7746
+ };
7747
+ document.addEventListener("visibilitychange", refreshWhenVisible);
7748
+ const timer = window.setInterval(refreshWhenVisible, 6e4);
7749
+ return () => {
7750
+ window.clearInterval(timer);
7751
+ document.removeEventListener("visibilitychange", refreshWhenVisible);
7752
+ quotaFollowUp.current?.cancel();
7753
+ };
7754
+ }, [loadStatus]);
7755
+ const loginStatus = status?.login?.status;
7756
+ (0, react.useEffect)(() => {
7757
+ if (loginStatus !== "pending") return;
7758
+ let stopped = false;
7759
+ const timer = window.setInterval(() => {
7760
+ (async () => {
7761
+ try {
7762
+ const poll = await get("/login/status");
7763
+ if (stopped) return;
7764
+ if (poll.status === "complete") {
7765
+ setPasteValue("");
7766
+ await loadStatus();
7767
+ onModelChange?.();
7768
+ } else if (poll.status === "error") setError(poll.error ?? t("loginError"));
7769
+ } catch {}
7770
+ })();
7771
+ }, LOGIN_POLL_INTERVAL_MS);
7772
+ return () => {
7773
+ stopped = true;
7774
+ window.clearInterval(timer);
7775
+ };
7776
+ }, [
7777
+ loginStatus,
7778
+ loadStatus,
7779
+ onModelChange,
7780
+ t
7781
+ ]);
7782
+ const setRegion = (0, react.useCallback)((next) => {
7783
+ regionTouched.current = true;
7784
+ setRegionState(next);
7785
+ }, []);
7786
+ (0, react.useEffect)(() => {
7787
+ setPasteOpen(loginStatus === "pending" || loginStatus === "error");
7788
+ }, [loginStatus]);
7789
+ const login = async (loginRegion) => {
7790
+ try {
7791
+ setBusy(`login:${loginRegion}`);
7792
+ setError(null);
7793
+ setConnection(null);
7794
+ setPasteValue("");
7795
+ const flow = await post$1("/login/start", { region: loginRegion });
7796
+ await loadStatus(true);
7797
+ if (flow.authorizeUrl !== void 0 && flow.authorizeUrl !== "") try {
7798
+ window.open(flow.authorizeUrl, "_blank", "noopener,noreferrer");
7799
+ } catch {}
7800
+ } catch (cause) {
7801
+ setError(messageOf(cause));
7802
+ } finally {
7803
+ setBusy(null);
7804
+ }
7805
+ };
7806
+ const cancelLogin = async () => {
7807
+ try {
7808
+ setBusy("login:cancel");
7809
+ setError(null);
7810
+ await post$1("/login/cancel", { region });
7811
+ await loadStatus(true);
7812
+ } catch (cause) {
7813
+ setError(messageOf(cause));
7814
+ } finally {
7815
+ setBusy(null);
7816
+ }
7817
+ };
7818
+ const submitPaste = async () => {
7819
+ if (pasteValue.trim() === "") {
7820
+ setError(t("manualPasteEmpty"));
7821
+ return;
7822
+ }
7823
+ try {
7824
+ setBusy("login-manual");
7825
+ setError(null);
7826
+ setStatus(await post$1("/login/manual", {
7827
+ region,
7828
+ code: pasteValue.trim()
7829
+ }));
7830
+ setPasteValue("");
7831
+ onModelChange?.();
7832
+ } catch (cause) {
7833
+ setError(messageOf(cause));
7834
+ } finally {
7835
+ setBusy(null);
7836
+ }
7837
+ };
7838
+ const adopt = async () => {
7839
+ try {
7840
+ setBusy("adopt");
7841
+ setError(null);
7842
+ const result = await post$1("/adopt", { region });
7843
+ setAdoptResult(result);
7844
+ await loadStatus(true);
7845
+ if (result.adopted) onModelChange?.();
7846
+ } catch (cause) {
7847
+ setError(messageOf(cause));
7848
+ } finally {
7849
+ setBusy(null);
7850
+ }
7851
+ };
7852
+ const accountAction = async (action, accountId) => {
7853
+ try {
7854
+ setBusy(`account:${action}:${accountId}`);
7855
+ setError(null);
7856
+ setStatus(await post$1("/accounts", {
7857
+ action,
7858
+ accountId
7859
+ }));
7860
+ onModelChange?.();
7861
+ } catch (cause) {
7862
+ setError(messageOf(cause));
7863
+ } finally {
7864
+ setBusy(null);
7865
+ }
7866
+ };
7867
+ const setStrategy = async (strategy) => {
7868
+ try {
7869
+ setBusy("strategy");
7870
+ setError(null);
7871
+ setStatus(await post$1("/accounts", {
7872
+ action: "strategy",
7873
+ strategy
7874
+ }));
7875
+ } catch (cause) {
7876
+ setError(messageOf(cause));
7877
+ } finally {
7878
+ setBusy(null);
7879
+ }
7880
+ };
7881
+ /** 一个模型勾选补丁;host 回整份新状态,卡片因此不必猜哪些 id 最终生效。 */
7882
+ const applyEnabledModels = async (enabledModelIds) => {
7883
+ try {
7884
+ setError(null);
7885
+ const updated = await post$1("/settings", { enabledModelIds });
7886
+ setStatus(updated);
7887
+ setContextDrafts(contextDraftsFor(updated));
7888
+ onModelChange?.();
7889
+ } catch (cause) {
7890
+ setError(messageOf(cause));
7891
+ }
7892
+ };
7893
+ const toggleModel = (modelId, enabled) => {
7894
+ if (status === null) return;
7895
+ const current = status.models.filter((model) => model.enabled).map((model) => model.id);
7896
+ const next = enabled ? [.../* @__PURE__ */ new Set([...current, modelId])] : current.filter((id) => id !== modelId);
7897
+ applyEnabledModels(next);
7898
+ };
7899
+ const setAllModels = (enabled) => {
7900
+ if (status === null || status.models.length === 0) return;
7901
+ applyEnabledModels(enabled ? status.models.map((model) => model.id) : []);
7902
+ };
7903
+ const saveContextWindow = async (modelId) => {
7904
+ const raw = contextDrafts[modelId] ?? "";
7905
+ const parsed = parsePositiveCapacity(raw);
7906
+ if (parsed === null) {
7907
+ setError(t("invalidCapacity").replace("{value}", raw));
7908
+ return;
7909
+ }
7910
+ try {
7911
+ setSavingModel(modelId);
7912
+ setError(null);
7913
+ setStatus(await post$1("/settings", { contextWindowOverrides: { [modelId]: parsed } }));
7914
+ setContextDrafts((previous) => ({
7915
+ ...previous,
7916
+ [modelId]: formatCapacity(parsed)
7917
+ }));
7918
+ onModelChange?.();
7919
+ } catch (cause) {
7920
+ setError(messageOf(cause));
7921
+ } finally {
7922
+ setSavingModel(null);
7923
+ }
7924
+ };
7925
+ const resetContextWindow = async (modelId) => {
7926
+ try {
7927
+ setSavingModel(modelId);
7928
+ setError(null);
7929
+ const updated = await post$1("/settings", { contextWindowOverrides: { [modelId]: null } });
7930
+ setStatus(updated);
7931
+ const model = updated.models.find((entry) => entry.id === modelId);
7932
+ if (model !== void 0) setContextDrafts((previous) => ({
7933
+ ...previous,
7934
+ [modelId]: formatCapacity(model.defaultContextWindow)
7935
+ }));
7936
+ onModelChange?.();
7937
+ } catch (cause) {
7938
+ setError(messageOf(cause));
7939
+ } finally {
7940
+ setSavingModel(null);
7941
+ }
7942
+ };
7943
+ const resetAllContextWindows = async () => {
7944
+ const ids = Object.keys(status?.contextWindowOverrides ?? {});
7945
+ if (ids.length === 0) return;
7946
+ try {
7947
+ setError(null);
7948
+ const updated = await post$1("/settings", { contextWindowOverrides: Object.fromEntries(ids.map((id) => [id, null])) });
7949
+ setStatus(updated);
7950
+ setContextDrafts(contextDraftsFor(updated));
7951
+ onModelChange?.();
7952
+ } catch (cause) {
7953
+ setError(messageOf(cause));
7954
+ }
7955
+ };
7956
+ const refreshQuota = async () => {
7957
+ try {
7958
+ setBusy("quota");
7959
+ setError(null);
7960
+ setStatus(await post$1("/quota", {}));
7961
+ } catch (cause) {
7962
+ setError(messageOf(cause));
7963
+ } finally {
7964
+ setBusy(null);
7965
+ }
7966
+ };
7967
+ const refreshCatalog = async () => {
7968
+ try {
7969
+ setBusy("catalog");
7970
+ setError(null);
7971
+ setStatus(await post$1("/catalog/refresh", {}));
7972
+ } catch (cause) {
7973
+ setError(messageOf(cause));
7974
+ } finally {
7975
+ setBusy(null);
7976
+ }
7977
+ };
7978
+ const testConnection = async () => {
7979
+ try {
7980
+ setBusy("connection");
7981
+ setError(null);
7982
+ setConnection(await post$1("/connection/test", {}));
7983
+ } catch (cause) {
7984
+ setError(messageOf(cause));
7985
+ } finally {
7986
+ setBusy(null);
7987
+ }
7988
+ };
7989
+ const accounts = glmAccounts(status);
7990
+ const models = status?.models ?? [];
7991
+ const contextModels = models.filter((model) => model.enabled);
7992
+ return {
7993
+ state: {
7994
+ status,
7995
+ loading,
7996
+ busy,
7997
+ error,
7998
+ connection,
7999
+ adoptResult,
8000
+ pasteValue,
8001
+ region,
8002
+ pasteOpen,
8003
+ contextDrafts,
8004
+ savingModel
8005
+ },
8006
+ derived: {
8007
+ accounts,
8008
+ models,
8009
+ contextModels,
8010
+ overrideCount: Object.keys(status?.contextWindowOverrides ?? {}).length,
8011
+ login: status?.login ?? null,
8012
+ quota: status?.quota ?? null,
8013
+ authenticated: status?.authenticated === true,
8014
+ poolLabels: accountPoolLabelsFor(t)
8015
+ },
8016
+ actions: {
8017
+ setRegion,
8018
+ login,
8019
+ cancelLogin,
8020
+ submitPaste,
8021
+ setPasteValue,
8022
+ togglePaste: () => setPasteOpen((previous) => !previous),
8023
+ adopt,
8024
+ clearAdoptResult: () => setAdoptResult(null),
8025
+ accountAction,
8026
+ setStrategy,
8027
+ toggleModel,
8028
+ setAllModels,
8029
+ saveContextWindow,
8030
+ resetContextWindow,
8031
+ resetAllContextWindows,
8032
+ updateContextDraft: (modelId, draft) => {
8033
+ setContextDrafts((previous) => ({
8034
+ ...previous,
8035
+ [modelId]: draft
8036
+ }));
8037
+ },
8038
+ refreshQuota,
8039
+ refreshCatalog,
8040
+ testConnection
8041
+ }
8042
+ };
8043
+ }
8044
+ //#endregion
8045
+ //#region src/client/glm-coding-plan/GlmCodingPlanSection.tsx
8046
+ /**
8047
+ * GLM(ZCode 账号)设置卡片。
8048
+ *
8049
+ * 纯渲染:状态、副作用与请求都在 'useGlmCodingPlanSection.ts',两者之间只通过
8050
+ * 一个具名结构交接(WorkBuddySection / MinimaxCodeSection 同款分工)。
8051
+ *
8052
+ * 三条需求方的 UI 硬要求由现成共享组件承担,本文件没有新建任何 UI 组件:
8053
+ *
8054
+ * 1. 进入入口(hub 卡片:图标 + 名称 + 「N 个账号 / M/N 个模型可用」+ 开关 + chevron)
8055
+ * —— hub/providers.tsx 的 descriptor + hub/HubOverview.tsx,点进来就是本卡片;
8056
+ * 2. 配额显示额度(标签 + 进度条 + 百分比 + 「N 天后重置」)
8057
+ * —— AccountPoolSection 的 showQuota + common/account-quota.tsx,
8058
+ * 窗口名由共享组件按 windowDurationMins 本地化(5 小时 / 1 周 / 1 月),
8059
+ * 所以本页的配额区只画「没有账号卡进度条可画」的那些事实;
8060
+ * 3. 模型选择(品牌图标 + 模型名 + 一句话描述 + 行尾勾)
8061
+ * —— common/ModelChecklist.tsx,hint 直接用契约里的 GlmModelOption.hint
8062
+ * (host 由随包目录生成,客户端不从模型名推断任何能力)。
8063
+ */
8064
+ /** 区域的人类可读名,登录与 adopt 两条入口的结果都要说清楚落在哪一区。 */
8065
+ function regionLabel(region) {
8066
+ return region === "cn" ? zh$3.regionCn : zh$3.regionIntl;
8067
+ }
8068
+ function GlmCodingPlanSection({ onModelChange } = {}) {
8069
+ const { state, derived, actions } = useGlmCodingPlanSection({ onModelChange });
8070
+ const { status, loading, busy, error, connection, adoptResult, pasteValue, region, pasteOpen, contextDrafts, savingModel } = state;
8071
+ const { accounts, models, contextModels, overrideCount, login, quota, authenticated, poolLabels } = derived;
8072
+ const { setRegion, login: startLogin, cancelLogin, submitPaste, setPasteValue, togglePaste, adopt, clearAdoptResult, accountAction, setStrategy, toggleModel, setAllModels, saveContextWindow, resetContextWindow, resetAllContextWindows, updateContextDraft, refreshQuota, refreshCatalog, testConnection } = actions;
8073
+ const t = zh$3;
8074
+ if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8075
+ className: "dsha-page",
8076
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8077
+ className: "dsha-empty",
8078
+ children: t.loading
8079
+ })
8080
+ });
8081
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8082
+ className: "dsha-page",
8083
+ children: [
8084
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8085
+ className: "dsha-muted",
8086
+ children: t.pageDesc
8087
+ }),
8088
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8089
+ className: "dsha-group",
8090
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8091
+ className: "dsha-grouphead",
8092
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.title })
8093
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8094
+ className: "dsha-pref-row",
8095
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.region }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8096
+ className: "dsha-muted",
8097
+ children: t.regionHint
8098
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
8099
+ className: "dsha-select",
8100
+ "aria-label": t.region,
8101
+ value: region,
8102
+ disabled: busy !== null,
8103
+ onChange: (event) => setRegion(event.currentTarget.value),
8104
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
8105
+ value: "cn",
8106
+ children: t.regionCn
8107
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
8108
+ value: "intl",
8109
+ children: t.regionIntl
8110
+ })]
8111
+ })]
8112
+ })]
8113
+ }),
8114
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
8115
+ accounts,
8116
+ activeAccountId: status?.activeAccountId,
8117
+ rotationStrategy: status?.rotationStrategy ?? "sequential",
8118
+ labels: poolLabels,
8119
+ busy,
8120
+ showQuota: true,
8121
+ onLogin: () => void startLogin(region),
8122
+ onSetPrimary: (accountId) => void accountAction("set-primary", accountId),
8123
+ onDelete: (accountId) => void accountAction("delete", accountId),
8124
+ onClearCooldown: (accountId) => void accountAction("clear-cooldown", accountId),
8125
+ onRelogin: (accountId) => void accountAction("relogin", accountId),
8126
+ onSetStrategy: (strategy) => void setStrategy(strategy),
8127
+ renderLoginActions: () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8128
+ className: "dsha-account-add-actions",
8129
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8130
+ className: "dsha-btn dsha-btn-primary",
8131
+ disabled: busy !== null,
8132
+ onClick: () => void startLogin("cn"),
8133
+ children: busy === "login:cn" ? t.authorizing : t.addCnAccount
8134
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8135
+ className: "dsha-btn dsha-btn-primary",
8136
+ disabled: busy !== null,
8137
+ onClick: () => void startLogin("intl"),
8138
+ children: busy === "login:intl" ? t.authorizing : t.addIntlAccount
8139
+ })]
8140
+ }),
8141
+ renderDetails: (account) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8142
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
8143
+ t.region,
8144
+ ": ",
8145
+ regionLabel(account.region)
8146
+ ] }),
8147
+ account.accountName ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: account.accountName }) : null,
8148
+ account.organizationId ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8149
+ className: "dshglm-mono",
8150
+ title: account.organizationId,
8151
+ children: account.organizationId
8152
+ }) : null
8153
+ ] }),
8154
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8155
+ className: "dshglm-flow",
8156
+ children: [
8157
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.loginSection }),
8158
+ login !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8159
+ login.status === "idle" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8160
+ className: "dsha-muted",
8161
+ children: t.loginIdle
8162
+ }),
8163
+ login.status === "pending" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8164
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8165
+ className: "dsha-muted",
8166
+ children: t.loginPending
8167
+ }),
8168
+ login.authorizeUrl !== void 0 && login.authorizeUrl !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
8169
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8170
+ className: "dsha-label",
8171
+ children: t.authorizeUrl
8172
+ }),
8173
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
8174
+ className: "dshglm-flow-url",
8175
+ children: login.authorizeUrl
8176
+ }),
8177
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8178
+ className: "dsha-actions",
8179
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
8180
+ className: "dsha-btn",
8181
+ href: login.authorizeUrl,
8182
+ target: "_blank",
8183
+ rel: "noreferrer noopener",
8184
+ children: t.openAuthorizeUrl
8185
+ })
8186
+ })
8187
+ ] }),
8188
+ login.progress !== void 0 && login.progress !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8189
+ className: "dsha-row",
8190
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8191
+ className: "dsha-label",
8192
+ children: t.progress
8193
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8194
+ className: "dsha-value",
8195
+ children: login.progress
8196
+ })]
8197
+ }),
8198
+ login.pollIntervalSec !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8199
+ className: "dsha-muted",
8200
+ children: t.pollEvery.replace("{seconds}", String(login.pollIntervalSec))
8201
+ }),
8202
+ login.expiresAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8203
+ className: "dsha-muted",
8204
+ children: t.loginExpiresAt.replace("{time}", formatDate(login.expiresAt))
8205
+ })
8206
+ ] }),
8207
+ login.status === "complete" && !authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8208
+ className: "dsha-muted",
8209
+ children: t.loginCompleteNoAccount
8210
+ }),
8211
+ login.status === "complete" && authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
8212
+ className: "dsha-notice",
8213
+ children: [t.loginComplete, login.email !== void 0 && login.email !== "" ? ` ${login.email}` : ""]
8214
+ }), login.completedAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8215
+ className: "dsha-muted",
8216
+ children: t.loginCompletedAt.replace("{time}", formatDate(login.completedAt))
8217
+ })] }),
8218
+ login.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8219
+ className: "dsha-error",
8220
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: login.error !== void 0 && login.error !== "" ? `${t.loginError} ${login.error}` : t.loginError }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: login.retryable === true ? t.loginRetryable : t.loginNotRetryable })]
8221
+ }),
8222
+ login.status === "pending" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8223
+ className: "dsha-actions",
8224
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8225
+ className: "dsha-btn",
8226
+ disabled: busy !== null,
8227
+ onClick: () => void cancelLogin(),
8228
+ children: busy === "login:cancel" ? t.cancelLoginBusy : t.cancelLogin
8229
+ })
8230
+ })
8231
+ ] }),
8232
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8233
+ className: "dsha-actions",
8234
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8235
+ className: "dsha-btn",
8236
+ disabled: busy !== null,
8237
+ onClick: () => void adopt(),
8238
+ children: busy === "adopt" ? t.adopting : t.adopt
8239
+ })
8240
+ }),
8241
+ adoptResult !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8242
+ className: "dsha-row",
8243
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8244
+ className: "dsha-value",
8245
+ children: adoptResult.adopted ? t.adoptAdopted.replace("{region}", regionLabel(adoptResult.region ?? region)) : adoptResult.reason === void 0 ? t.adoptNoAttempt : `${adoptReasonText(adoptResult.reason, t)} ${t.adoptFallback}`
8246
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8247
+ className: "dsha-btn",
8248
+ disabled: busy !== null,
8249
+ onClick: clearAdoptResult,
8250
+ children: t.dismiss
8251
+ })]
8252
+ }),
8253
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8254
+ className: "dshglm-paste",
8255
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8256
+ type: "button",
8257
+ className: "dsha-btn",
8258
+ "aria-expanded": pasteOpen,
8259
+ "aria-controls": "dshglm-paste-body",
8260
+ onClick: togglePaste,
8261
+ children: t.manualPasteSection
8262
+ }), pasteOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8263
+ id: "dshglm-paste-body",
8264
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8265
+ className: "dsha-muted",
8266
+ children: t.manualPasteHint
8267
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8268
+ className: "dshglm-paste-row",
8269
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
8270
+ type: "text",
8271
+ className: "dsha-select",
8272
+ "aria-label": t.manualPasteSection,
8273
+ placeholder: t.manualPastePlaceholder,
8274
+ value: pasteValue,
8275
+ disabled: busy !== null,
8276
+ onChange: (event) => setPasteValue(event.currentTarget.value),
8277
+ onKeyDown: (event) => {
8278
+ if (event.key === "Enter") submitPaste();
8279
+ }
8280
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8281
+ className: "dsha-btn dsha-btn-primary",
8282
+ disabled: busy !== null || pasteValue.trim() === "",
8283
+ onClick: () => void submitPaste(),
8284
+ children: busy === "login-manual" ? t.manualPasteSubmitting : t.manualPasteSubmit
8285
+ })]
8286
+ })]
8287
+ })]
8288
+ })
8289
+ ]
8290
+ })
8291
+ }),
8292
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8293
+ className: "dsha-group",
8294
+ children: [
8295
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8296
+ className: "dsha-grouphead",
8297
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.connection })
8298
+ }),
8299
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8300
+ className: "dsha-notice",
8301
+ children: status?.serving === false && status.conflict ? t.routeConflict.replace("{detail}", status.conflict) : t.routeOwned
8302
+ }),
8303
+ connection !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8304
+ className: connection.connected ? "dsha-muted" : "dsha-notice",
8305
+ children: connection.connected ? [
8306
+ t.testSuccess,
8307
+ t.testLatency.replace("{ms}", String(connection.latencyMs)),
8308
+ connection.account?.alias ?? connection.account?.accountName ?? null,
8309
+ connection.model ?? null
8310
+ ].filter((part) => part !== null && part !== "").join(" · ") : t.testFailedDetail.replace("{detail}", connection.error ?? "—")
8311
+ }),
8312
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8313
+ className: "dsha-actions",
8314
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8315
+ className: "dsha-btn",
8316
+ disabled: busy !== null || !authenticated,
8317
+ onClick: () => void testConnection(),
8318
+ children: busy === "connection" ? t.testingConnection : t.testConnection
8319
+ })
8320
+ })
8321
+ ]
8322
+ }),
8323
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8324
+ className: "dsha-group",
8325
+ children: [
8326
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8327
+ className: "dsha-grouphead",
8328
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.modelsSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8329
+ className: "dsha-btn",
8330
+ disabled: busy !== null,
8331
+ onClick: () => void refreshCatalog(),
8332
+ children: busy === "catalog" ? t.refreshingCatalog : t.refreshCatalog
8333
+ })]
8334
+ }),
8335
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8336
+ className: "dsha-muted dsha-models-hint",
8337
+ children: t.modelsHint
8338
+ }),
8339
+ models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8340
+ className: "dsha-empty",
8341
+ children: t.modelsUnavailable
8342
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelChecklist, {
8343
+ items: models.map((model) => ({
8344
+ id: model.id,
8345
+ name: model.name,
8346
+ hint: model.hint === "" ? void 0 : model.hint,
8347
+ enabled: model.enabled
8348
+ })),
8349
+ busy: busy !== null,
8350
+ onToggle: toggleModel,
8351
+ onToggleAll: setAllModels,
8352
+ labels: {
8353
+ selectAll: t.selectAll,
8354
+ clearAll: t.unselectAll,
8355
+ countTemplate: t.modelChecklistCount,
8356
+ list: t.modelsSection
8357
+ }
8358
+ })
8359
+ ]
8360
+ }),
8361
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8362
+ className: "dsha-group",
8363
+ children: [
8364
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8365
+ className: "dsha-grouphead",
8366
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.contextWindowSection })
8367
+ }),
8368
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8369
+ className: "dsha-muted",
8370
+ children: t.contextWindowHint
8371
+ }),
8372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextWindowEditor, {
8373
+ rows: contextModels.map((model) => ({
8374
+ id: model.id,
8375
+ name: model.name,
8376
+ draft: contextDrafts[model.id] ?? "",
8377
+ meta: model.defaultContextWindow < model.contextWindow ? formatCapacity(model.contextWindow) : void 0,
8378
+ inputLabel: `${model.name} ${t.contextWindowSection}`,
8379
+ hasOverride: status?.contextWindowOverrides[model.id] !== void 0,
8380
+ saving: savingModel === model.id
8381
+ })),
8382
+ labels: {
8383
+ tokens: t.tokens,
8384
+ save: t.save,
8385
+ saving: t.saving,
8386
+ reset: t.contextWindowReset,
8387
+ resetAll: t.contextWindowResetAll,
8388
+ empty: t.contextWindowNoneEnabled
8389
+ },
8390
+ busy: busy !== null,
8391
+ overrideCount,
8392
+ metaClassName: "dshglm-model-meta",
8393
+ onDraftChange: updateContextDraft,
8394
+ onCommit: (id) => void saveContextWindow(id),
8395
+ onReset: (id) => void resetContextWindow(id),
8396
+ onResetAll: () => void resetAllContextWindows()
8397
+ })
8398
+ ]
8399
+ }),
8400
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8401
+ className: "dsha-group",
8402
+ children: [
8403
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8404
+ className: "dsha-grouphead",
8405
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8406
+ className: "dsha-btn",
8407
+ disabled: busy !== null || !authenticated,
8408
+ onClick: () => void refreshQuota(),
8409
+ children: busy === "quota" ? t.quotaRefreshing : t.quotaRefresh
8410
+ })]
8411
+ }),
8412
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8413
+ className: "dsha-muted",
8414
+ children: t.quotaDesc
8415
+ }),
8416
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8417
+ className: "dsha-muted",
8418
+ children: poolLabels.quotaFactsScope
8419
+ }),
8420
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8421
+ className: "dsha-muted",
8422
+ children: t.quotaWindowNames
8423
+ }),
8424
+ status?.quotaRefreshing === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8425
+ className: "dsha-notice",
8426
+ children: t.quotaRefreshingNote
8427
+ }),
8428
+ status?.quotaError !== void 0 && status.quotaError !== null && status.quotaError !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8429
+ className: "dsha-notice",
8430
+ children: `${t.quotaErrorLabel}: ${status.quotaError}`
8431
+ }),
8432
+ authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8433
+ className: "dsha-row",
8434
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8435
+ className: "dsha-label",
8436
+ children: t.quotaAllowance
8437
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8438
+ className: "dsha-value",
8439
+ children: allowanceKindText(status?.allowance ?? quota?.allowance, t)
8440
+ })]
8441
+ }),
8442
+ authenticated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8443
+ className: "dsha-muted",
8444
+ children: t.quotaAllowanceHint
8445
+ }),
8446
+ !authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8447
+ className: "dsha-empty",
8448
+ children: t.quotaSignedOut
8449
+ }) : quota === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8450
+ className: "dsha-empty",
8451
+ children: busy === "quota" ? t.quotaRefreshing : t.quotaEmpty
8452
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8453
+ className: "dsha-quota-card",
8454
+ children: [
8455
+ quota.planLevel !== null && quota.planLevel !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8456
+ className: "dsha-quota-title",
8457
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota.planName ?? t.quotaPlan }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
8458
+ t.quotaPlanLevel,
8459
+ ": ",
8460
+ quota.planLevel
8461
+ ] })]
8462
+ }),
8463
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8464
+ className: "dsha-row",
8465
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8466
+ className: "dsha-label",
8467
+ children: t.quotaRenews
8468
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8469
+ className: "dsha-value",
8470
+ children: formatDate(quota.renewsAt)
8471
+ })]
8472
+ }),
8473
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8474
+ className: "dsha-row",
8475
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8476
+ className: "dsha-label",
8477
+ children: t.quotaReadAt
8478
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8479
+ className: "dsha-value",
8480
+ children: formatDate(quota.fetchedAt)
8481
+ })]
8482
+ }),
8483
+ quota.sources.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8484
+ className: "dsha-row",
8485
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8486
+ className: "dsha-label",
8487
+ children: t.quotaSources
8488
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8489
+ className: "dsha-value dshglm-mono",
8490
+ children: quota.sources.join(" · ")
8491
+ })]
8492
+ }),
8493
+ quota.windows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8494
+ className: "dsha-empty",
8495
+ children: t.quotaEmpty
8496
+ })
8497
+ ]
8498
+ })
8499
+ ]
8500
+ }),
8501
+ error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8502
+ className: "dsha-error",
8503
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: error })
8504
+ })
8505
+ ]
8506
+ });
8507
+ }
8508
+ //#endregion
8509
+ //#region src/shared/claude-contracts.ts
8510
+ /**
8511
+ * Every thinking level this route can name, in escalating order.
8512
+ *
8513
+ * The union of the whole shipped catalog rather than one model's ladder: these
8514
+ * are WIRE effort values, already collapsed by the upstream reference mapping
8515
+ * the frozen catalog transcribes ('minimal' and 'low' both send 'low', so
8516
+ * offering both would advertise a distinction the wire cannot make). The card
8517
+ * offers them as default-effort choices and narrows the dropdown per model with
8518
+ * {@link ClaudeModelOption.reasoningEfforts}.
8519
+ *
8520
+ * 'off' is deliberately absent, exactly as it is from every ladder in the
8521
+ * catalog: turning thinking off is the ABSENCE of a thinking block rather than
8522
+ * an effort level, and whether a model permits it is stated separately in
8523
+ * {@link ClaudeModelOption.canDisableThinking}.
8524
+ *
8525
+ * NOT derived from the catalog by an indexed access — the client project cannot
8526
+ * read that module. The equivalence is asserted against the real table in
8527
+ * 'src/host/claude/routes.ts'; see the module comment.
8528
+ */
8529
+ const CLAUDE_REASONING_EFFORTS = [
8530
+ "low",
8531
+ "medium",
8532
+ "high",
8533
+ "xhigh",
8534
+ "max"
8535
+ ];
8536
+ //#endregion
8537
+ //#region src/client/claude/locales.ts
8538
+ /**
8539
+ * Locale namespace of the Claude subscription tab.
8540
+ *
8541
+ * Its own namespace rather than the hub's, so a missing string surfaces as this
8542
+ * dictionary's key rather than as a wrong sentence borrowed from another
8543
+ * provider — the same reason every sibling line has one.
8544
+ */
8545
+ const NS_CLAUDE = "dsh-claude";
8546
+ const zh$2 = {
8547
+ ...accountPoolZh,
8548
+ title: "Claude(订阅)",
8549
+ pageDesc: "登录 Claude Pro/Max 订阅,管理模型、思考档位、上下文窗口与额度。",
8550
+ account: "账号",
8551
+ signedIn: "已登录",
8552
+ signedOut: "未登录",
8553
+ email: "邮箱",
8554
+ plan: "套餐",
8555
+ planUnknown: "—",
8556
+ subscriptionType: "订阅类型",
8557
+ source: "来源",
8558
+ sourceManaged: "本插件登录",
8559
+ sourceClaudeCode: "本机 Claude Code",
8560
+ adoptedBadge: "导入的快照",
8561
+ signIn: "登录 Claude 账号",
8562
+ signInSection: "登录授权",
8563
+ signInAgain: "重新登录",
8564
+ signingIn: "正在发起登录...",
8565
+ cancelSignIn: "取消登录",
8566
+ openAuthorizeUrl: "打开授权页面",
8567
+ authorizeUrl: "授权链接",
8568
+ redirectUri: "回调地址",
8569
+ loginModeManual: "当前是手动模式:浏览器回调不可用,授权完成后把页面上的 code 粘贴到下方输入框。",
8570
+ loginModeLoopback: "当前是本地回环模式:浏览器授权完成后会自动回到本机回调地址。",
8571
+ loginFallbackReason: "本地回环模式不可用,已降级为手动模式:{detail}",
8572
+ loginWaiting: "等待浏览器中的授权完成...",
8573
+ loginExchanging: "正在交换令牌...",
8574
+ loginComplete: "登录完成",
8575
+ loginFailed: "登录失败",
8576
+ manualPasteSection: "手动粘贴授权码",
8577
+ manualPasteHint: "把浏览器地址栏里的 code(或整段回调 URL)粘贴到这里完成登录。手动模式下没有浏览器回调,这里是唯一的入口。",
8578
+ manualPastePlaceholder: "code#state 或完整的回调 URL",
8579
+ manualPasteSubmit: "提交授权码",
8580
+ manualPasteSubmitting: "提交中...",
8581
+ importClaudeCode: "导入本机 Claude Code 登录态",
7401
8582
  importing: "导入中...",
7402
8583
  stopImporting: "停止导入",
7403
8584
  connection: "连接",
@@ -9133,6 +10314,12 @@ window.__ModuleLoader__.load({
9133
10314
  setEnabled: (enabled) => postLineSettings(MINIMAX_CODE_ROUTE_PREFIX, { enabled }),
9134
10315
  renderDetail: ({ onModelChange }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MinimaxCodeSection, { onModelChange })
9135
10316
  },
10317
+ {
10318
+ id: "glm-coding-plan",
10319
+ name: GLM_CODING_PLAN_PROVIDER_NAME,
10320
+ setEnabled: (enabled) => postLineSettings(GLM_CODING_PLAN_ROUTE_PREFIX, { enabled }),
10321
+ renderDetail: ({ onModelChange }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlmCodingPlanSection, { onModelChange })
10322
+ },
9136
10323
  {
9137
10324
  id: "claude",
9138
10325
  name: "Claude",
@@ -9987,7 +11174,7 @@ window.__ModuleLoader__.load({
9987
11174
  }
9988
11175
  //#endregion
9989
11176
  //#region src/client/antigravity/styles.ts
9990
- const STYLE_ID$4 = "dsh-antigravity-settings-style";
11177
+ const STYLE_ID$5 = "dsh-antigravity-settings-style";
9991
11178
  function installAntigravityStyles() {
9992
11179
  installPluginStyle("antigravity", `
9993
11180
  .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}
@@ -10057,7 +11244,7 @@ window.__ModuleLoader__.load({
10057
11244
  .dsha-account-details{display:flex;flex-wrap:wrap;gap:14px;font-size:12px;color:var(--dsw-alias-label-secondary)}
10058
11245
  .dsha-account-actions{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
10059
11246
  .dsha-account-actions .dsha-btn{padding:5px 10px;font-size:12px}
10060
- `, STYLE_ID$4);
11247
+ `, STYLE_ID$5);
10061
11248
  }
10062
11249
  //#endregion
10063
11250
  //#region src/client/common/styles.ts
@@ -10225,7 +11412,7 @@ window.__ModuleLoader__.load({
10225
11412
  }
10226
11413
  }
10227
11414
  /** The allowance the selected model actually draws on, as the badge's facts. */
10228
- function selectBadgeFacts$5(status, modelId) {
11415
+ function selectBadgeFacts$6(status, modelId) {
10229
11416
  const info = selectQuotaBucketForModel(status?.quota?.groups ?? [], modelId);
10230
11417
  if (info === null) return {
10231
11418
  text: "—",
@@ -10245,7 +11432,7 @@ window.__ModuleLoader__.load({
10245
11432
  loadModelDirectory,
10246
11433
  providerId: "antigravity",
10247
11434
  readStatus: (refresh) => refresh ? api$5.post("/quota") : api$5.get("/status"),
10248
- selectFacts: selectBadgeFacts$5,
11435
+ selectFacts: selectBadgeFacts$6,
10249
11436
  label: t("composerLabel")
10250
11437
  });
10251
11438
  }
@@ -10267,7 +11454,7 @@ window.__ModuleLoader__.load({
10267
11454
  * remaining is 100 - used. A window at 0% used is the normal empty state and
10268
11455
  * grades as 'normal', not as an error.
10269
11456
  */
10270
- function selectBadgeFacts$4(status) {
11457
+ function selectBadgeFacts$5(status) {
10271
11458
  const quota = status?.quota;
10272
11459
  if (quota === null || quota === void 0) return {
10273
11460
  text: "—",
@@ -10301,13 +11488,13 @@ window.__ModuleLoader__.load({
10301
11488
  loadModelDirectory,
10302
11489
  providerId: "claude-subscription",
10303
11490
  readStatus: (refresh) => refresh ? api$4.post("/quota") : api$4.get("/status"),
10304
- selectFacts: selectBadgeFacts$4,
11491
+ selectFacts: selectBadgeFacts$5,
10305
11492
  label: t("composerLabel")
10306
11493
  });
10307
11494
  }
10308
11495
  //#endregion
10309
11496
  //#region src/client/claude/styles.ts
10310
- const STYLE_ID$3 = "dsh-claude-settings-style";
11497
+ const STYLE_ID$4 = "dsh-claude-settings-style";
10311
11498
  /**
10312
11499
  * Claude-only additions to the shared settings design system.
10313
11500
  *
@@ -10331,7 +11518,7 @@ window.__ModuleLoader__.load({
10331
11518
  .dshcl-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;overflow-wrap:anywhere}
10332
11519
  .dshcl-model-meta{color:var(--dsw-alias-label-tertiary);font-size:11px;margin-left:5px}
10333
11520
  .dshcl-empty-inline{color:var(--dsw-alias-label-tertiary);font-size:12px}
10334
- `, STYLE_ID$3);
11521
+ `, STYLE_ID$4);
10335
11522
  }
10336
11523
  //#endregion
10337
11524
  //#region src/client/command-code/CommandCodeComposerQuota.tsx
@@ -10342,7 +11529,7 @@ window.__ModuleLoader__.load({
10342
11529
  * A bounded usage window is the number a user actually spends down, so it wins
10343
11530
  * over a credit balance; the balance shows only when no window is reported.
10344
11531
  */
10345
- function selectBadgeFacts$3(status) {
11532
+ function selectBadgeFacts$4(status) {
10346
11533
  const quota = status?.quota;
10347
11534
  if (quota === null || quota === void 0) return {
10348
11535
  text: "—",
@@ -10389,7 +11576,7 @@ window.__ModuleLoader__.load({
10389
11576
  loadModelDirectory,
10390
11577
  providerId: "command-code",
10391
11578
  readStatus: (refresh) => refresh ? api$3.post("/quota") : api$3.get("/status"),
10392
- selectFacts: selectBadgeFacts$3,
11579
+ selectFacts: selectBadgeFacts$4,
10393
11580
  label: t("composerLabel")
10394
11581
  });
10395
11582
  }
@@ -10403,7 +11590,7 @@ window.__ModuleLoader__.load({
10403
11590
  * blocks work soonest, so it wins over the longer pools; the 7-day allowance
10404
11591
  * shows only when no 5-hour window is reported.
10405
11592
  */
10406
- function selectBadgeFacts$2(status) {
11593
+ function selectBadgeFacts$3(status) {
10407
11594
  const quota = status?.quota;
10408
11595
  if (quota === null || quota === void 0) return {
10409
11596
  text: "—",
@@ -10440,13 +11627,13 @@ window.__ModuleLoader__.load({
10440
11627
  loadModelDirectory,
10441
11628
  providerId: "kimi-code",
10442
11629
  readStatus: (refresh) => refresh ? api$2.post("/quota") : api$2.get("/status"),
10443
- selectFacts: selectBadgeFacts$2,
11630
+ selectFacts: selectBadgeFacts$3,
10444
11631
  label: t("composerLabel")
10445
11632
  });
10446
11633
  }
10447
11634
  //#endregion
10448
11635
  //#region src/client/kimi-code/styles.ts
10449
- const STYLE_ID$2 = "dsh-kimi-code-settings-style";
11636
+ const STYLE_ID$3 = "dsh-kimi-code-settings-style";
10450
11637
  /**
10451
11638
  * Node the base control styles come from.
10452
11639
  *
@@ -10531,7 +11718,7 @@ window.__ModuleLoader__.load({
10531
11718
  `;
10532
11719
  /** Kimi-specific rules layered on top of the shared control styles. */
10533
11720
  function installKimiCodeStyles() {
10534
- installPluginStyle("kimi-code", BASE, STYLE_ID$2);
11721
+ installPluginStyle("kimi-code", BASE, STYLE_ID$3);
10535
11722
  }
10536
11723
  //#endregion
10537
11724
  //#region src/client/minimax-code/MinimaxCodeComposerQuota.tsx
@@ -10545,7 +11732,7 @@ window.__ModuleLoader__.load({
10545
11732
  * is not rendered, rather than showing a placeholder that would read as a broken
10546
11733
  * meter. Callers must treat null as "hide the badge".
10547
11734
  */
10548
- function selectBadgeFacts$1(status) {
11735
+ function selectBadgeFacts$2(status) {
10549
11736
  const quota = status?.quota;
10550
11737
  if (quota === void 0) return null;
10551
11738
  if (quota.usedPercent !== void 0 && Number.isFinite(quota.usedPercent)) {
@@ -10568,13 +11755,13 @@ window.__ModuleLoader__.load({
10568
11755
  loadModelDirectory,
10569
11756
  providerId: "minimax-code",
10570
11757
  readStatus: () => api$1.get("/quota"),
10571
- selectFacts: selectBadgeFacts$1,
11758
+ selectFacts: selectBadgeFacts$2,
10572
11759
  label: t("composerLabel")
10573
11760
  });
10574
11761
  }
10575
11762
  //#endregion
10576
11763
  //#region src/client/minimax-code/styles.ts
10577
- const STYLE_ID$1 = "dsh-minimax-code-settings-style";
11764
+ const STYLE_ID$2 = "dsh-minimax-code-settings-style";
10578
11765
  /**
10579
11766
  * MiniMax Code-only additions to the shared settings design system.
10580
11767
  *
@@ -10590,7 +11777,7 @@ window.__ModuleLoader__.load({
10590
11777
  .dshm-model-list{display:flex;flex-wrap:wrap;gap:7px;padding-top:8px}
10591
11778
  .dshm-model-list code{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-secondary);font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;padding:5px 8px;white-space:nowrap}
10592
11779
  .dshm-quota-note{margin-top:12px}
10593
- `, STYLE_ID$1);
11780
+ `, STYLE_ID$2);
10594
11781
  }
10595
11782
  //#endregion
10596
11783
  //#region src/client/workbuddy/WorkBuddyComposerQuota.tsx
@@ -10603,7 +11790,7 @@ window.__ModuleLoader__.load({
10603
11790
  * payload reports both a cycle meter and a package meter, and the cycle meter
10604
11791
  * is the one that actually resets, so it is preferred when both exist.
10605
11792
  */
10606
- function selectBadgeFacts(status) {
11793
+ function selectBadgeFacts$1(status) {
10607
11794
  const quota = status?.quota;
10608
11795
  if (quota === null || quota === void 0) return {
10609
11796
  text: "—",
@@ -10636,13 +11823,13 @@ window.__ModuleLoader__.load({
10636
11823
  loadModelDirectory,
10637
11824
  providerId: "workbuddy-subscription",
10638
11825
  readStatus: (refresh) => refresh ? api.post("/quota") : api.get("/status"),
10639
- selectFacts: selectBadgeFacts,
11826
+ selectFacts: selectBadgeFacts$1,
10640
11827
  label: t("composerLabel")
10641
11828
  });
10642
11829
  }
10643
11830
  //#endregion
10644
11831
  //#region src/client/workbuddy/styles.ts
10645
- const STYLE_ID = "dsh-workbuddy-settings-style";
11832
+ const STYLE_ID$1 = "dsh-workbuddy-settings-style";
10646
11833
  /**
10647
11834
  * WorkBuddy-only additions to the shared settings design system.
10648
11835
  *
@@ -10661,6 +11848,84 @@ window.__ModuleLoader__.load({
10661
11848
  .dsha-account-add-actions{display:flex;flex-wrap:wrap;gap:8px}
10662
11849
  .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)}
10663
11850
  .dsha-account-add-actions .dsha-btn:hover:not(:disabled){opacity:.9;background:var(--dsw-alias-button-info-fill,#397ee8)}
11851
+ `, STYLE_ID$1);
11852
+ }
11853
+ //#endregion
11854
+ //#region src/client/glm-coding-plan/GlmCodingPlanComposerQuota.tsx
11855
+ /**
11856
+ * 胶囊显示「最紧的那个窗口」的剩余百分比。
11857
+ *
11858
+ * 三个窗口(5 小时 / 1 周 / 1 月)互相独立地重置,用户当下真正被卡住的是**已用比例
11859
+ * 最高**的那一个:另外两个可能还剩一大半。所以这里不平均、不取最小剩余,而是取最大
11860
+ * 已用;已用相等时取更短的窗口——重置更早的那个才是当下的瓶颈。
11861
+ *
11862
+ * 窗口名不硬编码:键映射成窗口长度后交给共享的 quotaWindowLabel 本地化
11863
+ * (5 小时 / 1 周 / 1 月 / 5 hours / 1 week / 1 month)。
11864
+ *
11865
+ * 没有快照、没有窗口、或全部窗口都没有百分比时返回 null,即**不渲染胶囊**:
11866
+ * 契约允许 quota 为 null,装一个占位数字比不显示更像坏了。
11867
+ */
11868
+ function selectBadgeFacts(status, lookup = (key) => zh$3[key]) {
11869
+ const measured = (status?.quota?.windows ?? []).filter((window) => typeof window.usedPercent === "number" && Number.isFinite(window.usedPercent));
11870
+ if (measured.length === 0) return null;
11871
+ const tightest = measured.reduce((best, window) => {
11872
+ const bestMinutes = QUOTA_WINDOW_MINUTES[best.key];
11873
+ const minutes = QUOTA_WINDOW_MINUTES[window.key];
11874
+ if ((window.usedPercent ?? 0) > (best.usedPercent ?? 0)) return window;
11875
+ if ((window.usedPercent ?? 0) < (best.usedPercent ?? 0)) return best;
11876
+ return minutes < bestMinutes ? window : best;
11877
+ });
11878
+ const used = Math.max(0, Math.min(100, tightest.usedPercent ?? 0));
11879
+ const remaining = Math.round(100 - used);
11880
+ const label = quotaWindowLabel({
11881
+ label: "",
11882
+ usedPercent: used,
11883
+ windowDurationMins: QUOTA_WINDOW_MINUTES[tightest.key]
11884
+ }, {
11885
+ ...accountPoolZh,
11886
+ quotaWindow: lookup("quotaWindow")
11887
+ });
11888
+ return {
11889
+ text: `${remaining}%`,
11890
+ tooltip: `[${lookup("title")}] ${label}: ${remaining}% ${lookup("composerLabel")}`,
11891
+ level: quotaLevel(remaining)
11892
+ };
11893
+ }
11894
+ function GlmCodingPlanComposerQuota({ directory, loadModelDirectory, t }) {
11895
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComposerQuotaBadge, {
11896
+ directory,
11897
+ loadModelDirectory,
11898
+ providerId: GLM_CODING_PLAN_PROVIDER_ID,
11899
+ readStatus: (refresh) => refresh ? post$1("/quota", {}) : get("/status"),
11900
+ selectFacts: (status) => selectBadgeFacts(status, t),
11901
+ label: t("composerLabel")
11902
+ });
11903
+ }
11904
+ //#endregion
11905
+ //#region src/client/glm-coding-plan/styles.ts
11906
+ const STYLE_ID = "dsh-glm-coding-plan-settings-style";
11907
+ /**
11908
+ * GLM(ZCode 账号)卡片独有的样式。
11909
+ *
11910
+ * 共享样式一律不重复声明:模型清单(.dsh-mcl-*)由 common/model-checklist-styles.ts
11911
+ * 负责,账号卡与配额条(.dsha-account-*)由 common/styles.ts 负责,基础控件
11912
+ * (.dsha-page / .dsha-group / .dsha-row / 胶囊等)由兄弟线路的安装器负责。
11913
+ * 本文件只声明没有兄弟线路共用过的东西:登录流程块、手工粘贴行、等宽文本、
11914
+ * 模型行右侧的窗口数字,以及「导入的登录态」徽标。
11915
+ *
11916
+ * 两区登录入口复用的 .dsha-account-add-actions 由 workbuddy/styles.ts 声明;
11917
+ * Claude 卡片同样直接用它而不在自己文件里重复声明,本卡沿用同一做法。
11918
+ */
11919
+ function installGlmCodingPlanStyles() {
11920
+ installPluginStyle("glm-coding-plan", `
11921
+ .dshglm-flow{border-bottom:0.5px solid var(--dsw-alias-border-l2);display:flex;flex-direction:column;gap:10px;padding:12px 0}
11922
+ .dshglm-flow-url{background:var(--dsw-alias-bg-layer-1,rgba(127,127,127,.14));border:0.5px solid var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-primary);font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;overflow-wrap:anywhere;padding:8px 10px;user-select:all}
11923
+ .dshglm-paste{align-items:flex-start;display:flex;flex-direction:column;gap:8px}
11924
+ .dshglm-paste-row{align-items:center;display:flex;flex-wrap:wrap;gap:8px}
11925
+ .dshglm-paste-row input{flex:1 1 260px;min-width:200px}
11926
+ .dshglm-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;overflow-wrap:anywhere}
11927
+ .dshglm-model-meta{color:var(--dsw-alias-label-tertiary);font-size:11px;margin-left:5px}
11928
+ .dsha-badge.glm-adopted{background:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 16%,var(--dsw-alias-bg-layer-1));border-color:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 45%,var(--dsw-alias-border-l2));color:var(--dsw-alias-label-primary)}
10664
11929
  `, STYLE_ID);
10665
11930
  }
10666
11931
  //#endregion
@@ -11007,7 +12272,7 @@ window.__ModuleLoader__.load({
11007
12272
  installModelChecklistStyles();
11008
12273
  return () => {};
11009
12274
  }, "dsh-chatgpt-subscription: hub styles");
11010
- ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$7), "dsh-antigravity: dictionaries");
12275
+ ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$8), "dsh-antigravity: dictionaries");
11011
12276
  ctx.effect(() => {
11012
12277
  installAntigravityStyles();
11013
12278
  return () => {};
@@ -11017,18 +12282,23 @@ window.__ModuleLoader__.load({
11017
12282
  installClaudeStyles();
11018
12283
  return () => {};
11019
12284
  }, "dsh-claude: styles");
11020
- ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$6), "dsh-command-code: dictionaries");
11021
- ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$5), "dsh-kimi-code: dictionaries");
12285
+ ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$7), "dsh-command-code: dictionaries");
12286
+ ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$6), "dsh-kimi-code: dictionaries");
11022
12287
  ctx.effect(() => {
11023
12288
  installKimiCodeStyles();
11024
12289
  return () => {};
11025
12290
  }, "dsh-kimi-code: styles");
11026
- ctx.effect(() => ctx.locale.register(NS_MINIMAX_CODE, dictionaries$3), "dsh-minimax-code: dictionaries");
12291
+ ctx.effect(() => ctx.locale.register(NS_MINIMAX_CODE, dictionaries$4), "dsh-minimax-code: dictionaries");
11027
12292
  ctx.effect(() => {
11028
12293
  installMinimaxCodeStyles();
11029
12294
  return () => {};
11030
12295
  }, "dsh-minimax-code: styles");
11031
- ctx.effect(() => ctx.locale.register(NS_WORKBUDDY, dictionaries$4), "dsh-workbuddy: dictionaries");
12296
+ ctx.effect(() => ctx.locale.register(NS_WORKBUDDY, dictionaries$5), "dsh-workbuddy: dictionaries");
12297
+ ctx.effect(() => ctx.locale.register(NS_GLM_CODING_PLAN, dictionaries$3), "dsh-glm-coding-plan: dictionaries");
12298
+ ctx.effect(() => {
12299
+ installGlmCodingPlanStyles();
12300
+ return () => {};
12301
+ }, "dsh-glm-coding-plan: styles");
11032
12302
  ctx.effect(() => ctx.locale.register(NS_OLLAMA, dictionaries$1), "dsh-ollama: dictionaries");
11033
12303
  ctx.effect(() => {
11034
12304
  installWorkBuddyStyles();
@@ -11109,6 +12379,13 @@ window.__ModuleLoader__.load({
11109
12379
  locale: NS_CLAUDE,
11110
12380
  inject: (sessionId) => composerBadgeInject(ctx, sessionId)
11111
12381
  }, ClaudeComposerQuota));
12382
+ ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
12383
+ name: "conversation.input.right",
12384
+ id: "glm-coding-plan-quota",
12385
+ order: 42,
12386
+ locale: NS_GLM_CODING_PLAN,
12387
+ inject: (sessionId) => composerBadgeInject(ctx, sessionId)
12388
+ }, GlmCodingPlanComposerQuota));
11112
12389
  ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
11113
12390
  name: "tool.call.toolview",
11114
12391
  key: CODEX_IMAGE_TOOL_NAME,