@liyang8246/dsh-accounts 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -182,7 +182,8 @@
182
182
  }
183
183
  function activeQuota(snapshot, channel) {
184
184
  const quota = snapshot?.accounts.find((account) => account.channel === channel && account.active)?.quota;
185
- return quota?.status === "ok" ? measuredWindows(quota.windows) : [];
185
+ if (!quota) return [];
186
+ return measuredWindows(quota.windows);
186
187
  }
187
188
  function leftOf(window) {
188
189
  return window.exhausted ? 0 : Math.min(100, Math.max(0, 100 - window.usedPercent));
@@ -542,6 +543,7 @@
542
543
  }
543
544
  // src/client/composer-quota.tsx
544
545
  function createComposerQuota(React, ctx, store, QuotaBars) {
546
+ let lastChannel;
545
547
  return function ComposerQuota({ sessionId }) {
546
548
  React.useSyncExternalStore((fn) => ctx.locale.subscribe(fn), () => ctx.locale.getSnapshot());
547
549
  const models = ctx.get("modelDirectories");
@@ -554,7 +556,11 @@
554
556
  }, [models, sessionId]);
555
557
  const state = React.useSyncExternalStore(React.useCallback((listener) => modelStore ? modelStore.subscribe(listener) : () => {}, [modelStore]), React.useCallback(() => modelStore?.getSnapshot(), [modelStore]));
556
558
  const data = React.useSyncExternalStore(store.subscribe, store.getSnapshot);
557
- const channel = channelOf(state?.current?.provider);
559
+ const current = state?.current;
560
+ let channel;
561
+ if (current === null) channel = lastChannel;
562
+ else if (current !== void 0) channel = channelOf(current.provider);
563
+ if (channel !== void 0) lastChannel = channel;
558
564
  React.useEffect(() => {
559
565
  if (channel) store.reload().catch(() => {});
560
566
  }, [channel]);
@@ -698,7 +704,7 @@
698
704
  // src/client/quota.tsx
699
705
  function createQuotaComponents(React, t) {
700
706
  function Quota({ quota }) {
701
- const windows = quota?.status === "ok" ? measuredWindows(quota.windows) : [];
707
+ const windows = measuredWindows(quota?.windows ?? []);
702
708
  return /* @__PURE__ */ React.createElement("div", { className: windows.length ? void 0 : "zph-quota-unavailable" }, windows.length ? /* @__PURE__ */ React.createElement("div", { className: "zph-quota" }, windows.map((window) => /* @__PURE__ */ React.createElement("div", {
703
709
  key: window.period,
704
710
  className: "zph-window"
@@ -707,7 +713,7 @@
707
713
  "data-level": levelOf(window),
708
714
  role: "img",
709
715
  "aria-label": `${window.period} ${t("left")} ${Math.round(leftOf(window))}%`
710
- }, /* @__PURE__ */ React.createElement("b", { style: { width: `${leftOf(window)}%` } })), window.used !== void 0 && window.limit !== void 0 && /* @__PURE__ */ React.createElement("div", { className: "zph-muted" }, `${window.used} / ${window.limit} ${window.unit || ""}`)))) : /* @__PURE__ */ React.createElement("p", { className: "zph-muted" }, t(quota ? "unavailable" : "notFetched")), quota?.status === "ok" && quota.windows.filter((window) => window.period === "other").map((window, index) => /* @__PURE__ */ React.createElement("div", {
716
+ }, /* @__PURE__ */ React.createElement("b", { style: { width: `${leftOf(window)}%` } })), window.used !== void 0 && window.limit !== void 0 && /* @__PURE__ */ React.createElement("div", { className: "zph-muted" }, `${window.used} / ${window.limit} ${window.unit || ""}`)))) : /* @__PURE__ */ React.createElement("p", { className: "zph-muted" }, t(quota ? "unavailable" : "notFetched")), quota?.windows.filter((window) => window.period === "other").map((window, index) => /* @__PURE__ */ React.createElement("div", {
711
717
  className: "zph-muted",
712
718
  key: index
713
719
  }, `${window.label || t("other")}: ${window.usedPercent?.toFixed(1) ?? "—"}% ${t("used")}`)), quota?.reason && /* @__PURE__ */ React.createElement("p", { className: quota.status === "error" ? "zph-error" : "zph-muted" }, quota.reason));
package/lib/index.js CHANGED
@@ -7317,12 +7317,15 @@ var ModelAccountsService = class {
7317
7317
  this.accounts.saveQuota(id, quota).catch(() => {});
7318
7318
  }
7319
7319
  } catch (error) {
7320
- if (!this.controller.signal.aborted && (await this.accounts.list()).some((account) => account.id === id)) this.quotas.set(id, {
7321
- status: "error",
7322
- fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
7323
- windows: [],
7324
- reason: safeError(error)
7325
- });
7320
+ if (!this.controller.signal.aborted && (await this.accounts.list()).some((account) => account.id === id)) {
7321
+ const previous = await this.lastGoodQuota(id);
7322
+ this.quotas.set(id, {
7323
+ status: "error",
7324
+ fetchedAt: previous?.fetchedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
7325
+ windows: previous?.windows ?? [],
7326
+ reason: safeError(error)
7327
+ });
7328
+ }
7326
7329
  }
7327
7330
  })();
7328
7331
  this.fetching.set(id, operation);
@@ -7332,6 +7335,20 @@ var ModelAccountsService = class {
7332
7335
  this.fetching.delete(id);
7333
7336
  }
7334
7337
  }
7338
+ /**
7339
+ * Read the last measurement a failed refresh should keep showing.
7340
+ * @param id - account whose quota is being reported.
7341
+ * @returns the cached view, else the persisted one, else the bare cached one.
7342
+ */
7343
+ async lastGoodQuota(id) {
7344
+ const cached = this.quotas.get(id);
7345
+ if (cached?.windows.length) return cached;
7346
+ try {
7347
+ return (await this.accounts.quotas())[id] ?? cached;
7348
+ } catch {
7349
+ return cached;
7350
+ }
7351
+ }
7335
7352
  async resetCredit(id, signal) {
7336
7353
  const view = (await this.accounts.list()).find((account) => account.id === id);
7337
7354
  if (!view) throw new Error("Account not found");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@liyang8246/dsh-accounts",
3
3
  "type": "module",
4
- "version": "0.1.12",
4
+ "version": "0.1.13",
5
5
  "description": "Independent multi-account Codex, OpenCode Go and CommandCode Go plugin for DeepSeek Harness.",
6
6
  "repository": { "type": "git", "url": "https://github.com/liyang8246/dsh-zolin.git", "directory": "packages/dsh-accounts" },
7
7
  "exports": {