@eddyskywalker/dsh-chatgpt-subscription 0.42.0 → 0.43.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 (55) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +1 -0
  3. package/lib/client.js +256 -182
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +813 -237
  6. package/lib/types/client/command-code/CommandCodeComposerQuota.d.ts.map +1 -1
  7. package/lib/types/client/common/format.d.ts +16 -0
  8. package/lib/types/client/common/format.d.ts.map +1 -1
  9. package/lib/types/client/kimi-code/KimiCodeComposerQuota.d.ts.map +1 -1
  10. package/lib/types/client/kimi-code/KimiCodeSection.d.ts.map +1 -1
  11. package/lib/types/client/kimi-code/KimiQuotaCard.d.ts.map +1 -1
  12. package/lib/types/client/kimi-code/styles.d.ts.map +1 -1
  13. package/lib/types/client/locales-ru/opendesign.d.ts.map +1 -1
  14. package/lib/types/client/locales-ru/qoder.d.ts.map +1 -1
  15. package/lib/types/client/opendesign/OpenDesignSection.d.ts.map +1 -1
  16. package/lib/types/client/opendesign/locales.d.ts +12 -0
  17. package/lib/types/client/opendesign/locales.d.ts.map +1 -1
  18. package/lib/types/client/qoder/QoderSection.d.ts.map +1 -1
  19. package/lib/types/client/qoder/locales.d.ts +9 -1
  20. package/lib/types/client/qoder/locales.d.ts.map +1 -1
  21. package/lib/types/client/qoder/styles.d.ts.map +1 -1
  22. package/lib/types/compat.d.ts +1 -1
  23. package/lib/types/host/claude/types.d.ts +7 -1
  24. package/lib/types/host/claude/types.d.ts.map +1 -1
  25. package/lib/types/host/glm-coding-plan/types.d.ts +5 -1
  26. package/lib/types/host/glm-coding-plan/types.d.ts.map +1 -1
  27. package/lib/types/host/kimi-code/account-pool.d.ts +26 -1
  28. package/lib/types/host/kimi-code/account-pool.d.ts.map +1 -1
  29. package/lib/types/host/kimi-code/client.d.ts +24 -0
  30. package/lib/types/host/kimi-code/client.d.ts.map +1 -1
  31. package/lib/types/host/kimi-code/oauth.d.ts +16 -0
  32. package/lib/types/host/kimi-code/oauth.d.ts.map +1 -1
  33. package/lib/types/host/kimi-code/routes.d.ts.map +1 -1
  34. package/lib/types/host/opendesign/adapter.d.ts +11 -13
  35. package/lib/types/host/opendesign/adapter.d.ts.map +1 -1
  36. package/lib/types/host/opendesign/catalog.d.ts +14 -0
  37. package/lib/types/host/opendesign/catalog.d.ts.map +1 -1
  38. package/lib/types/host/opendesign/line.d.ts +17 -6
  39. package/lib/types/host/opendesign/line.d.ts.map +1 -1
  40. package/lib/types/host/opendesign/routes.d.ts.map +1 -1
  41. package/lib/types/host/opendesign/token-store.d.ts +91 -4
  42. package/lib/types/host/opendesign/token-store.d.ts.map +1 -1
  43. package/lib/types/host/opendesign/types.d.ts.map +1 -1
  44. package/lib/types/host/qoder/client.d.ts.map +1 -1
  45. package/lib/types/host/qoder/mapper.d.ts +74 -2
  46. package/lib/types/host/qoder/mapper.d.ts.map +1 -1
  47. package/lib/types/host/qoder/types.d.ts +6 -1
  48. package/lib/types/host/qoder/types.d.ts.map +1 -1
  49. package/lib/types/host/step-code/types.d.ts +5 -1
  50. package/lib/types/host/step-code/types.d.ts.map +1 -1
  51. package/lib/types/shared/opendesign-contracts.d.ts +24 -1
  52. package/lib/types/shared/opendesign-contracts.d.ts.map +1 -1
  53. package/lib/types/shared/qoder-contracts.d.ts +10 -0
  54. package/lib/types/shared/qoder-contracts.d.ts.map +1 -1
  55. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -146,11 +146,11 @@ window.__ModuleLoader__.load({
146
146
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
147
147
  className: "dsh-codex-composer-quota",
148
148
  "data-level": quota === null ? "normal" : quota.remainingPercent <= 5 ? "danger" : quota.remainingPercent <= 20 ? "warning" : "normal",
149
- "aria-label": quota === null ? t("quickQuotaLoading") : `${t("quickQuotaLabel")}: ${formatPercent$1(quota.remainingPercent)}`,
150
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quickQuotaLabel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota === null ? loading ? t("quickQuotaLoading") : "—" : formatPercent$1(quota.remainingPercent) })]
149
+ "aria-label": quota === null ? t("quickQuotaLoading") : `${t("quickQuotaLabel")}: ${formatPercent$2(quota.remainingPercent)}`,
150
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quickQuotaLabel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota === null ? loading ? t("quickQuotaLoading") : "—" : formatPercent$2(quota.remainingPercent) })]
151
151
  });
152
152
  }
153
- function formatPercent$1(value) {
153
+ function formatPercent$2(value) {
154
154
  return `${new Intl.NumberFormat(void 0, { maximumFractionDigits: 0 }).format(value)}%`;
155
155
  }
156
156
  //#endregion
@@ -1147,6 +1147,26 @@ window.__ModuleLoader__.load({
1147
1147
  if (value >= 1e3) return Math.round(value / 1e3) + "k";
1148
1148
  return String(value);
1149
1149
  }
1150
+ /**
1151
+ * A share as a person reads it: at most `digits` decimals, no trailing zeros.
1152
+ *
1153
+ * The formatting has to happen on the RESULT rather than on its inputs. Most
1154
+ * percentages on these cards are a remainder — `100 - used` — and that
1155
+ * subtraction is exactly where binary floating point shows up: `100 - 8.04` is
1156
+ * `91.96000000000001`, `100 - 0.0007 * 100` is `99.93` but `100 - 0.0014 * 100`
1157
+ * is `99.86` only because it happens to land on a friendly neighbour. String
1158
+ * interpolation of the difference therefore prints a long tail for roughly a
1159
+ * third of all two-decimal inputs, which reads as "sometimes" — and no amount of
1160
+ * rounding the used share beforehand fixes a subtraction done afterwards.
1161
+ *
1162
+ * Anything non-finite renders as `0`, because every caller has already decided
1163
+ * the window is measured; this is the last line of defence, not a claim.
1164
+ */
1165
+ function formatPercent$1(value, digits = 2) {
1166
+ if (!Number.isFinite(value)) return "0";
1167
+ const factor = 10 ** Math.min(6, Math.max(0, Math.trunc(digits)));
1168
+ return String(Math.round(value * factor) / factor);
1169
+ }
1150
1170
  /** A stamp in the reader's own locale, or an em dash when there is none. */
1151
1171
  function formatDate$1(ms) {
1152
1172
  if (ms === void 0 || ms === null || !Number.isFinite(ms) || ms <= 0) return "—";
@@ -5420,10 +5440,12 @@ window.__ModuleLoader__.load({
5420
5440
  const SHORT_PER_WEEK = 5;
5421
5441
  /** 5 小时窗口在月额度里的份数。 */
5422
5442
  const SHORT_PER_MONTH = 25;
5423
- /** 百分比,最多两位小数;非有限数不画。 */
5443
+ /** 提示条箭头离气泡两端的最小距离,免得圆角把三角切掉。 */
5444
+ const ARROW_INSET = 12;
5445
+ /** 百分比,最多两位小数;非有限数不画。舍入规则放在共享的 `formatPercent`。 */
5424
5446
  function percentText$2(value) {
5425
5447
  if (!Number.isFinite(value)) return "0%";
5426
- return `${Math.round(value * 100) / 100}%`;
5448
+ return `${formatPercent$1(value)}%`;
5427
5449
  }
5428
5450
  /** `YYYY-MM-DD HH:mm`,本地时区;令牌到期用它,年份不能省。 */
5429
5451
  function dateText(ms) {
@@ -5513,6 +5535,43 @@ window.__ModuleLoader__.load({
5513
5535
  const timer = window.setInterval(() => setClock(Date.now()), 3e4);
5514
5536
  return () => window.clearInterval(timer);
5515
5537
  }, [shortReset]);
5538
+ const tipPercent = Math.max(0, Math.min(100, totalPercent));
5539
+ const barRef = (0, react.useRef)(null);
5540
+ const tipRef = (0, react.useRef)(null);
5541
+ const [tipPlacement, setTipPlacement] = (0, react.useState)({
5542
+ shift: 0,
5543
+ arrowPx: null
5544
+ });
5545
+ (0, react.useEffect)(() => {
5546
+ const wrap = barRef.current;
5547
+ const tip = tipRef.current;
5548
+ if (wrap === null || tip === null) return void 0;
5549
+ const place = () => {
5550
+ const width = wrap.clientWidth;
5551
+ const bubble = tip.offsetWidth;
5552
+ if (width <= 0 || bubble <= 0) {
5553
+ setTipPlacement({
5554
+ shift: 0,
5555
+ arrowPx: null
5556
+ });
5557
+ return;
5558
+ }
5559
+ const half = bubble / 2;
5560
+ const anchor = width * tipPercent / 100;
5561
+ const clamped = Math.min(Math.max(anchor, half), Math.max(half, width - half));
5562
+ const arrow = Math.min(Math.max(anchor - (clamped - half), ARROW_INSET), bubble - ARROW_INSET);
5563
+ setTipPlacement({
5564
+ shift: Math.round((clamped - anchor) * 10) / 10,
5565
+ arrowPx: Math.round(arrow * 10) / 10
5566
+ });
5567
+ };
5568
+ place();
5569
+ if (typeof ResizeObserver === "undefined") return void 0;
5570
+ const observer = new ResizeObserver(place);
5571
+ observer.observe(wrap);
5572
+ observer.observe(tip);
5573
+ return () => observer.disconnect();
5574
+ }, [tipPercent]);
5516
5575
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5517
5576
  className: "dsha-kq",
5518
5577
  children: [
@@ -5564,6 +5623,8 @@ window.__ModuleLoader__.load({
5564
5623
  }),
5565
5624
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5566
5625
  className: "dsha-kq-barwrap",
5626
+ ref: barRef,
5627
+ style: { "--kq-tip-x": `${tipPercent}%` },
5567
5628
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5568
5629
  className: "dsha-kq-meter dsha-kq-meter--total",
5569
5630
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -5578,6 +5639,11 @@ window.__ModuleLoader__.load({
5578
5639
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5579
5640
  className: "dsha-kq-tip",
5580
5641
  role: "tooltip",
5642
+ ref: tipRef,
5643
+ style: {
5644
+ "--kq-tip-shift": `${tipPlacement.shift}px`,
5645
+ ...tipPlacement.arrowPx === null ? {} : { "--kq-tip-arrow": `${tipPlacement.arrowPx}px` }
5646
+ },
5581
5647
  children: t.kqTip.replace("{pct}", percentText$2(totalPercent))
5582
5648
  })]
5583
5649
  }),
@@ -5623,19 +5689,6 @@ window.__ModuleLoader__.load({
5623
5689
  //#endregion
5624
5690
  //#region src/client/kimi-code/KimiCodeSection.tsx
5625
5691
  const api$12 = createLineApi("/kimi-code/api", "Kimi Code");
5626
- /** Money the service reports in minor units, rendered in its own currency. */
5627
- function formatMoney(cents, currency) {
5628
- if (cents === null) return "—";
5629
- const code = currency ?? "USD";
5630
- try {
5631
- return new Intl.NumberFormat(void 0, {
5632
- style: "currency",
5633
- currency: code
5634
- }).format(cents / 100);
5635
- } catch {
5636
- return `${(cents / 100).toFixed(2)} ${code}`;
5637
- }
5638
- }
5639
5692
  /**
5640
5693
  * One token count as the card prints it.
5641
5694
  *
@@ -6001,7 +6054,7 @@ window.__ModuleLoader__.load({
6001
6054
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6002
6055
  className: "dsha-page",
6003
6056
  children: [
6004
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
6057
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(AccountPoolSection, {
6005
6058
  accounts: status?.accounts ?? [],
6006
6059
  activeAccountId: status?.activeAccountId,
6007
6060
  rotationStrategy: status?.rotationStrategy ?? "sequential",
@@ -6025,59 +6078,74 @@ window.__ModuleLoader__.load({
6025
6078
  now,
6026
6079
  labels: t
6027
6080
  }),
6028
- children: loginPending && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6029
- className: "dsha-device-box",
6030
- children: [
6031
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.deviceCodeSection }),
6032
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6033
- className: "dsha-muted",
6034
- children: t.deviceCodeHint
6035
- }),
6036
- flow?.userCode && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6037
- className: "dsha-code-row",
6038
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6039
- className: "dsha-code",
6040
- children: flow.userCode
6041
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6042
- className: "dsha-btn",
6043
- onClick: () => void handleCopyCode(),
6044
- children: copied ? t.copied : t.copyCode
6045
- })]
6046
- }),
6047
- flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
6048
- className: "dsha-link",
6049
- href: flow.verificationUriComplete,
6050
- target: "_blank",
6051
- rel: "noreferrer noopener",
6052
- children: flow.verificationUriComplete
6053
- }),
6054
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6055
- className: "dsha-row",
6056
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6057
- className: "dsha-label",
6058
- children: t.codeExpires
6059
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6060
- className: "dsha-value",
6061
- children: formatDate$1(flow?.expiresAt)
6062
- })]
6063
- }),
6064
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6065
- className: "dsha-actions",
6066
- children: [flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
6067
- className: "dsha-btn",
6081
+ children: [
6082
+ loginPending && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6083
+ className: "dsha-device-box",
6084
+ children: [
6085
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.deviceCodeSection }),
6086
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6087
+ className: "dsha-muted",
6088
+ children: t.deviceCodeHint
6089
+ }),
6090
+ flow?.userCode && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6091
+ className: "dsha-code-row",
6092
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6093
+ className: "dsha-code",
6094
+ children: flow.userCode
6095
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6096
+ className: "dsha-btn",
6097
+ onClick: () => void handleCopyCode(),
6098
+ children: copied ? t.copied : t.copyCode
6099
+ })]
6100
+ }),
6101
+ flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
6102
+ className: "dsha-link",
6068
6103
  href: flow.verificationUriComplete,
6069
6104
  target: "_blank",
6070
6105
  rel: "noreferrer noopener",
6071
- children: t.openSignInPage
6072
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6073
- className: "dsha-btn",
6074
- disabled: busy !== null,
6075
- onClick: () => void handleCancelLogin(),
6076
- children: t.cancelSignIn
6077
- })]
6106
+ children: flow.verificationUriComplete
6107
+ }),
6108
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6109
+ className: "dsha-row",
6110
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6111
+ className: "dsha-label",
6112
+ children: t.codeExpires
6113
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6114
+ className: "dsha-value",
6115
+ children: formatDate$1(flow?.expiresAt)
6116
+ })]
6117
+ }),
6118
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6119
+ className: "dsha-actions",
6120
+ children: [flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
6121
+ className: "dsha-btn",
6122
+ href: flow.verificationUriComplete,
6123
+ target: "_blank",
6124
+ rel: "noreferrer noopener",
6125
+ children: t.openSignInPage
6126
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6127
+ className: "dsha-btn",
6128
+ disabled: busy !== null,
6129
+ onClick: () => void handleCancelLogin(),
6130
+ children: t.cancelSignIn
6131
+ })]
6132
+ })
6133
+ ]
6134
+ }),
6135
+ status?.quotaError != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6136
+ className: "dsha-notice",
6137
+ children: status.quotaError
6138
+ }),
6139
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6140
+ className: "dsha-actions",
6141
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6142
+ className: "dsha-btn",
6143
+ disabled: busy !== null || !status?.authenticated,
6144
+ onClick: () => void handleRefreshQuota(),
6145
+ children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
6078
6146
  })
6079
- ]
6080
- })
6147
+ })
6148
+ ]
6081
6149
  }),
6082
6150
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6083
6151
  className: "dsha-group",
@@ -6365,69 +6433,6 @@ window.__ModuleLoader__.load({
6365
6433
  })
6366
6434
  ]
6367
6435
  }),
6368
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6369
- className: "dsha-group",
6370
- children: [
6371
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6372
- className: "dsha-grouphead",
6373
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6374
- className: "dsha-btn",
6375
- disabled: busy !== null || !status?.authenticated,
6376
- onClick: () => void handleRefreshQuota(),
6377
- children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
6378
- })]
6379
- }),
6380
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6381
- className: "dsha-muted",
6382
- children: t.quotaDesc
6383
- }),
6384
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6385
- className: "dsha-muted",
6386
- children: t.quotaFactsScope
6387
- }),
6388
- status?.quotaError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6389
- className: "dsha-notice",
6390
- children: status.quotaError
6391
- }),
6392
- !status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6393
- className: "dsha-empty",
6394
- children: t.signedOut
6395
- }) : quota === null || quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6396
- className: "dsha-empty",
6397
- children: busy === "quota" ? t.refreshingQuota : t.quotaEmpty
6398
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6399
- className: "dsha-quota-card",
6400
- children: [
6401
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6402
- className: "dsha-quota-title",
6403
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.quotaPlan }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.planName || t.planUnknown })]
6404
- }),
6405
- quota.extraUsage !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6406
- className: "dsha-meter-wrap",
6407
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6408
- className: "dsha-meter-label",
6409
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaWallet }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatMoney(quota.extraUsage.balanceCents, quota.extraUsage.currency) })]
6410
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6411
- className: "dsha-meter-meta",
6412
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatMoney(quota.extraUsage.totalCents, quota.extraUsage.currency) }), quota.extraUsage.monthlyChargeLimitEnabled && quota.extraUsage.monthlyChargeLimitCents !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6413
- t.quotaWalletLimit,
6414
- ": ",
6415
- formatMoney(quota.extraUsage.monthlyChargeLimitCents, quota.extraUsage.currency)
6416
- ] })]
6417
- })]
6418
- }),
6419
- quota.windows.length === 0 && quota.extraUsage === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6420
- className: "dsha-empty",
6421
- children: t.quotaEmpty
6422
- }),
6423
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6424
- className: "dsha-timestamp",
6425
- children: t.updatedAt.replace("{time}", new Date(quota.fetchedAt).toLocaleString())
6426
- })
6427
- ]
6428
- })
6429
- ]
6430
- }),
6431
6436
  error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6432
6437
  className: "dsha-error",
6433
6438
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: error })
@@ -15960,6 +15965,10 @@ window.__ModuleLoader__.load({
15960
15965
  quotaSignedOut: "登录后这里显示账号的额度。",
15961
15966
  quotaErrorLabel: "额度读取失败",
15962
15967
  quotaNoUnit: "",
15968
+ /** 上游明说额度用尽:它是账号层面的事实,三只桶全是 0 时只有它能说清为什么被拒。 */
15969
+ quotaExceeded: "额度已用尽",
15970
+ quotaExceededHint: "上游说这个账号的额度已经用尽,请求会被拒。额度恢复之前发消息会失败:可以等周期重置,或在额度页升级套餐。",
15971
+ quotaUpgradeLink: "打开升级页面",
15963
15972
  cacheSection: "缓存用量",
15964
15973
  cacheStatScope: "本机统计(token 维度,自本进程启动累计):它回答「缓存帮了多少忙」,不是上游账单。",
15965
15974
  cacheDesc: "Qoder 服务端自动做前缀缓存;命中量从响应的 usage.prompt_tokens_details.cached_tokens 读出(缺失时读顶层 cached_tokens)。本线路订阅没有公开的 token 单价,整页只显示 token 数字,不显示金额。",
@@ -16080,6 +16089,9 @@ window.__ModuleLoader__.load({
16080
16089
  quotaSignedOut: "Sign in to see the account's quota here.",
16081
16090
  quotaErrorLabel: "Quota read failed",
16082
16091
  quotaNoUnit: "",
16092
+ quotaExceeded: "Quota exhausted",
16093
+ quotaExceededHint: "Upstream says this account's quota is exhausted, so requests get rejected. Sending a message fails until the quota resets: wait for the period to reset, or upgrade the plan on the quota page.",
16094
+ quotaUpgradeLink: "Open the upgrade page",
16083
16095
  cacheSection: "Cache usage",
16084
16096
  cacheStatScope: "Local statistics (tokens, accumulated since this process started): it answers \"how much the cache helped\", not the upstream bill.",
16085
16097
  cacheDesc: "Qoder caches prefixes automatically server-side; hits are read from usage.prompt_tokens_details.cached_tokens (falling back to a top-level cached_tokens). There is no public per-token price for the subscription, so this page shows token counts only, never money.",
@@ -17193,49 +17205,71 @@ window.__ModuleLoader__.load({
17193
17205
  children: busy === "quota" ? t.quotaRefreshing : t.quotaEmpty
17194
17206
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17195
17207
  className: "dsha-quota-card",
17196
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17197
- className: "dshq-fact-grid",
17198
- children: [
17199
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17200
- className: "dshq-fact",
17201
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaExpiresAt }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.expiresAt !== null ? formatDate$1(quota.expiresAt) : "—" })]
17202
- }),
17203
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17204
- className: "dshq-fact",
17205
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaReadAt }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatDate$1(quota.fetchedAt) })]
17206
- }),
17207
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17208
- className: "dshq-fact",
17209
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaRegion }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: regionText(quota.region, t) })]
17210
- })
17211
- ]
17212
- }), quota.buckets.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17213
- className: "dsha-empty",
17214
- children: t.quotaEmpty
17215
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17216
- className: "dshq-quota-list",
17217
- children: quota.buckets.map((bucket, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17218
- className: "dshq-quota-row",
17208
+ children: [
17209
+ quota.quotaExceeded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17210
+ className: "dshq-quota-exhausted",
17219
17211
  children: [
17220
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17221
- className: "dshq-quota-name",
17222
- children: quotaBucketText(bucket.kind, t)
17212
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17213
+ className: "dshq-quota-exhausted-title",
17214
+ children: t.quotaExceeded
17223
17215
  }),
17224
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17225
- className: "dshq-quota-value",
17226
- children: bucketAmountText(bucket, t)
17216
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17217
+ className: "dshq-quota-exhausted-hint",
17218
+ children: t.quotaExceededHint
17227
17219
  }),
17228
- bucket.used !== null && bucket.total !== null && bucket.total > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
17229
- className: "dshq-quota-meta",
17230
- children: [
17231
- t.quotaUsed,
17232
- " ",
17233
- percentText(bucket.used / bucket.total)
17234
- ]
17220
+ quota.upgradeUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
17221
+ href: quota.upgradeUrl,
17222
+ target: "_blank",
17223
+ rel: "noreferrer noopener",
17224
+ children: t.quotaUpgradeLink
17235
17225
  })
17236
17226
  ]
17237
- }, bucket.kind + ":" + index))
17238
- })]
17227
+ }),
17228
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17229
+ className: "dshq-fact-grid",
17230
+ children: [
17231
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17232
+ className: "dshq-fact",
17233
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaExpiresAt }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.expiresAt !== null ? formatDate$1(quota.expiresAt) : "—" })]
17234
+ }),
17235
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17236
+ className: "dshq-fact",
17237
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaReadAt }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatDate$1(quota.fetchedAt) })]
17238
+ }),
17239
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17240
+ className: "dshq-fact",
17241
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaRegion }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: regionText(quota.region, t) })]
17242
+ })
17243
+ ]
17244
+ }),
17245
+ quota.buckets.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17246
+ className: "dsha-empty",
17247
+ children: t.quotaEmpty
17248
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17249
+ className: "dshq-quota-list",
17250
+ children: quota.buckets.map((bucket, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17251
+ className: "dshq-quota-row",
17252
+ children: [
17253
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17254
+ className: "dshq-quota-name",
17255
+ children: quotaBucketText(bucket.kind, t)
17256
+ }),
17257
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17258
+ className: "dshq-quota-value",
17259
+ children: bucketAmountText(bucket, t)
17260
+ }),
17261
+ bucket.used !== null && bucket.total !== null && bucket.total > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
17262
+ className: "dshq-quota-meta",
17263
+ children: [
17264
+ t.quotaUsed,
17265
+ " ",
17266
+ percentText(bucket.used / bucket.total)
17267
+ ]
17268
+ })
17269
+ ]
17270
+ }, bucket.kind + ":" + index))
17271
+ })
17272
+ ]
17239
17273
  }),
17240
17274
  moreNotes(t.moreNotes, [t.quotaDesc])
17241
17275
  ]
@@ -17375,6 +17409,8 @@ window.__ModuleLoader__.load({
17375
17409
  catalogSyncedNote: "实时目录已同步 {count} 个模型。",
17376
17410
  noModels: "暂无可用模型。",
17377
17411
  pricingNote: "价格为官方公开价目(美元 / 每百万 token,输入 / 输出)。",
17412
+ unservedBadge: "套餐不支持",
17413
+ unservedHint: "当前套餐不提供的模型默认隐藏,勾选后会强制显示。",
17378
17414
  contextSection: "上下文窗口",
17379
17415
  contextHint: "官方未公布各模型的上下文窗口:默认按 128k 处理,可在这里按模型修正。留空或保存无效值会提示错误;恢复默认会清掉覆盖值。",
17380
17416
  tokens: "tokens",
@@ -17481,6 +17517,8 @@ window.__ModuleLoader__.load({
17481
17517
  catalogSyncedNote: "Live catalog synced: {count} model(s).",
17482
17518
  noModels: "No models available.",
17483
17519
  pricingNote: "Prices are the official public list (USD per 1M tokens, input / output).",
17520
+ unservedBadge: "Not in plan",
17521
+ unservedHint: "Models the current plan does not serve stay hidden by default; checking one here forces it to show.",
17484
17522
  contextSection: "Context windows",
17485
17523
  contextHint: "The vendor publishes no per-model context windows, so models default to 128k; correct any model here. An invalid value is reported rather than saved; restoring clears the override.",
17486
17524
  tokens: "tokens",
@@ -17583,6 +17621,19 @@ window.__ModuleLoader__.load({
17583
17621
  return Math.min(100, Math.max(0, value));
17584
17622
  }
17585
17623
  /**
17624
+ * Whether the plan the gateway bills for withholds this model.
17625
+ *
17626
+ * The host adds `served: false` to a catalog entry the current plan does not
17627
+ * provide. Such a row stays listed — unchecking it is what hides it, and
17628
+ * checking it is how a user forces it visible — so the card labels it rather
17629
+ * than dropping it. The field is optional: `true` and an absent field both mean
17630
+ * served, so the badge and the note never appear for them and every row renders
17631
+ * exactly as it did before this marker existed.
17632
+ */
17633
+ function unserved(model) {
17634
+ return model.served === false;
17635
+ }
17636
+ /**
17586
17637
  * A window's length in the words the service sold it in.
17587
17638
  *
17588
17639
  * A policy states seconds, and the tier's windows are round days and hours:
@@ -18325,6 +18376,11 @@ window.__ModuleLoader__.load({
18325
18376
  style: { fontSize: 12 },
18326
18377
  children: t.modelsHint
18327
18378
  }),
18379
+ models.some(unserved) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
18380
+ className: "dsha-muted",
18381
+ style: { fontSize: 12 },
18382
+ children: t.unservedHint
18383
+ }),
18328
18384
  status !== null && models.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
18329
18385
  className: "dsha-empty",
18330
18386
  children: t.noModels
@@ -18336,12 +18392,15 @@ window.__ModuleLoader__.load({
18336
18392
  children: t.catalogNeverSynced
18337
18393
  }),
18338
18394
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelChecklist, {
18339
- items: models.map((model) => ({
18340
- id: model.id,
18341
- name: model.name,
18342
- hint: model.hint ?? `${formatCapacity$1(model.contextWindow)} · ${model.input.join("+")}${model.reasoning ? " · reasoning" : ""}`,
18343
- enabled: model.enabled
18344
- })),
18395
+ items: models.map((model) => {
18396
+ const hint = model.hint ?? `${formatCapacity$1(model.contextWindow)} · ${model.input.join("+")}${model.reasoning ? " · reasoning" : ""}`;
18397
+ return {
18398
+ id: model.id,
18399
+ name: model.name,
18400
+ hint: unserved(model) ? `${hint} · ${t.unservedBadge}` : hint,
18401
+ enabled: model.enabled
18402
+ };
18403
+ }),
18345
18404
  busy: busyAny,
18346
18405
  onToggle: (id, enabled) => toggleModel(id, enabled),
18347
18406
  onToggleAll: (enabled) => setAllModels(enabled),
@@ -20872,6 +20931,8 @@ window.__ModuleLoader__.load({
20872
20931
  catalogSyncedNote: "Живой каталог синхронизирован: моделей {count}.",
20873
20932
  noModels: "Доступных моделей нет.",
20874
20933
  pricingNote: "Цены — официальный публичный прайс (доллары США за 1 млн токенов, вход / выход).",
20934
+ unservedBadge: "Нет в тарифе",
20935
+ unservedHint: "Модели, которых нет в текущем тарифе, по умолчанию скрыты; отметьте их здесь, чтобы показать принудительно.",
20875
20936
  contextSection: "Контекстные окна",
20876
20937
  contextHint: "Производитель не публикует контекстные окна по моделям, поэтому по умолчанию берётся 128k; здесь любую модель можно поправить. Неверное значение не сохраняется, а показывается ошибкой; восстановление сбрасывает переопределение.",
20877
20938
  tokens: "токены",
@@ -21066,6 +21127,9 @@ window.__ModuleLoader__.load({
21066
21127
  quotaSignedOut: "Войдите, чтобы увидеть здесь квоту аккаунта.",
21067
21128
  quotaErrorLabel: "Не удалось прочитать квоту",
21068
21129
  quotaNoUnit: "",
21130
+ quotaExceeded: "Квота исчерпана",
21131
+ quotaExceededHint: "Апстрим сообщает, что квота этого аккаунта исчерпана, поэтому запросы отклоняются. Отправка сообщения не удастся, пока квота не восстановится: дождитесь сброса периода или смените тариф на странице квоты.",
21132
+ quotaUpgradeLink: "Открыть страницу тарифа",
21069
21133
  cacheSection: "Расход кеша",
21070
21134
  cacheStatScope: "Локальная статистика (в токенах, с начала работы процесса): она отвечает, насколько помог кеш, и не является счётом апстрима.",
21071
21135
  cacheDesc: "Qoder кеширует префиксы на сервере автоматически; попадания читаются из usage.prompt_tokens_details.cached_tokens (при отсутствии — из верхнеуровневого cached_tokens). У подписки нет публичной цены за токен, поэтому страница показывает только токены, без денег.",
@@ -21977,9 +22041,10 @@ window.__ModuleLoader__.load({
21977
22041
  const window = [...quota.windows ?? []].sort((a, b) => (a.windowDurationMins ?? Infinity) - (b.windowDurationMins ?? Infinity))[0];
21978
22042
  if (window !== void 0) {
21979
22043
  const remaining = Math.max(0, 100 - window.usedPercent);
22044
+ const remainingText = formatPercent$1(remaining);
21980
22045
  return {
21981
- text: `${remaining}%`,
21982
- tooltip: `[Command Code] ${window.label}: ${remaining}% left`,
22046
+ text: `${remainingText}%`,
22047
+ tooltip: `[Command Code] ${window.label}: ${remainingText}% left`,
21983
22048
  level: quotaLevel(remaining)
21984
22049
  };
21985
22050
  }
@@ -22038,9 +22103,10 @@ window.__ModuleLoader__.load({
22038
22103
  const window = [...quota.windows ?? []].filter((candidate) => candidate.windowDurationMins !== null).sort((a, b) => (a.windowDurationMins ?? Infinity) - (b.windowDurationMins ?? Infinity))[0] ?? quota.windows[0];
22039
22104
  if (window !== void 0) {
22040
22105
  const remaining = Math.max(0, 100 - window.usedPercent);
22106
+ const remainingText = formatPercent$1(remaining);
22041
22107
  return {
22042
- text: `${remaining}%`,
22043
- tooltip: `[Kimi Code] ${window.label}: ${remaining}% left`,
22108
+ text: `${remainingText}%`,
22109
+ tooltip: `[Kimi Code] ${window.label}: ${remainingText}% left`,
22044
22110
  level: quotaLevel(remaining)
22045
22111
  };
22046
22112
  }
@@ -22182,9 +22248,11 @@ window.__ModuleLoader__.load({
22182
22248
  .dsha-kq-seg{border-radius:999px;display:block;height:100%;transition:width .9s cubic-bezier(.22,.61,.36,1)}
22183
22249
  .dsha-kq-seg--recent{background:var(--kq-code)}
22184
22250
  .dsha-kq-seg--rest{background:var(--kq-rest)}
22185
- .dsha-kq-tip{background:var(--kq-tip-bg);border-radius:10px;bottom:calc(100% + 10px);color:var(--dsw-alias-bg-base,#fff);font-size:13px;line-height:1;opacity:0;padding:9px 14px;pointer-events:none;position:absolute;right:0;transform:translateY(4px);transition:opacity .16s ease-out,transform .16s ease-out;white-space:nowrap}
22186
- .dsha-kq-tip::after{border:6px solid transparent;border-top-color:var(--kq-tip-bg);content:"";position:absolute;right:34px;top:100%}
22187
- .dsha-kq-barwrap:hover .dsha-kq-tip{opacity:1;transform:translateY(0)}
22251
+ .dsha-kq-tip{background:var(--kq-tip-bg);border-radius:10px;bottom:calc(100% + 10px);color:var(--dsw-alias-bg-base,#fff);font-size:13px;line-height:1;left:var(--kq-tip-x,50%);opacity:0;padding:9px 14px;pointer-events:none;position:absolute;transform:translate(calc(-50% + var(--kq-tip-shift,0px)),4px);transition:opacity .16s ease-out,transform .16s ease-out;white-space:nowrap}
22252
+ /* 箭头不跟气泡的位移走:气泡被 --kq-tip-shift 收回卡片内时,箭头按
22253
+ --kq-tip-arrow 单独挪回「已用段末端」在气泡里的位置,所以它指的一直是那个数字。 */
22254
+ .dsha-kq-tip::after{border:6px solid transparent;border-top-color:var(--kq-tip-bg);content:"";left:var(--kq-tip-arrow,50%);margin-left:-6px;position:absolute;top:100%}
22255
+ .dsha-kq-barwrap:hover .dsha-kq-tip{opacity:1;transform:translate(calc(-50% + var(--kq-tip-shift,0px)),0)}
22188
22256
  .dsha-kq-legend{align-items:center;color:var(--kq-fg-2);column-gap:16px;display:flex;flex-wrap:wrap;font-size:13px;margin-top:11px;row-gap:6px}
22189
22257
  .dsha-kq-legend-item{align-items:center;display:inline-flex;gap:6px;white-space:nowrap}
22190
22258
  .dsha-kq-legend-note{color:var(--kq-fg-3);white-space:nowrap}
@@ -23347,6 +23415,12 @@ window.__ModuleLoader__.load({
23347
23415
  .dshq-quota-name{color:var(--dsw-alias-label-primary);font-size:12px;min-width:104px}
23348
23416
  .dshq-quota-value{color:var(--dsw-alias-label-secondary);font-size:12px}
23349
23417
  .dshq-quota-meta{color:var(--dsw-alias-label-tertiary);font-size:11px}
23418
+ /* 额度用尽:账号层面的一条事实(上游明说),与三只桶的数字并排给出。 */
23419
+ .dshq-quota-exhausted{margin-top:11px}
23420
+ .dshq-quota-exhausted-title{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600}
23421
+ .dshq-quota-exhausted-hint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;margin-top:4px}
23422
+ .dshq-quota-exhausted a{color:var(--dsw-alias-label-link,#397ee8);font-size:12px;text-decoration:none}
23423
+ .dshq-quota-exhausted a:hover{text-decoration:underline}
23350
23424
  /* 快照卡里的几行事实:紧凑网格,一格一件事,行高一致。 */
23351
23425
  .dshq-fact-grid{display:grid;gap:9px 20px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin-top:11px}
23352
23426
  .dshq-fact{display:flex;flex-direction:column;gap:3px;min-width:0}