@rayadesu/dsh-client-ui-billing 0.2.2 → 0.2.3

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 (2) hide show
  1. package/lib/client.js +32 -39
  2. package/package.json +3 -3
package/lib/client.js CHANGED
@@ -4277,6 +4277,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4277
4277
  return `¥${amount.toFixed(4).replace(/\.?0+$/, "")}`;
4278
4278
  }
4279
4279
  /**
4280
+ * Run one fetch line: the fetch is deferred to a microtask so the effect's
4281
+ * render commits before any state update lands; a settled value is stored
4282
+ * while `current` stays true, and a rejection keeps the previous value (a
4283
+ * no-op unless `onReject` supplies fallback handling) so a failed refetch
4284
+ * never blanks the UI.
4285
+ */
4286
+ function fetchLine(current, fetch, store, onReject) {
4287
+ return Promise.resolve().then(fetch).then((value) => {
4288
+ if (current()) store(value);
4289
+ }, (reason) => {
4290
+ if (current()) onReject?.(reason);
4291
+ });
4292
+ }
4293
+ /**
4280
4294
  * Render the billing badge in the session-header utilities row. The trigger
4281
4295
  * shows the remaining balance and this conversation's billed spend and opens
4282
4296
  * a label box with the amount, this session's spend with its cache-hit /
@@ -4305,24 +4319,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4305
4319
  const pricedRunningRef = (0, react.useRef)(running);
4306
4320
  (0, react.useEffect)(() => {
4307
4321
  let current = true;
4322
+ const isCurrent = () => current;
4308
4323
  setRefreshing(balance !== null);
4309
4324
  Promise.resolve().then(() => {
4310
- const balanceRequest = Promise.resolve().then(getBalance).then((value) => {
4311
- if (!current) return;
4325
+ const balanceRequest = fetchLine(isCurrent, getBalance, (value) => {
4312
4326
  setBalance(value);
4313
4327
  setError(null);
4314
4328
  }, (reason) => {
4315
- if (!current) return;
4316
4329
  if (balance === null) setError(reason instanceof Error ? reason.message : String(reason));
4317
4330
  });
4318
- const sessionSpendRequest = Promise.resolve().then(() => getSessionSpend(sessionId)).then((value) => {
4319
- if (!current) return;
4320
- setSpend(value);
4321
- }, () => {});
4322
- const todaySpendRequest = Promise.resolve().then(() => getTodaySpend(request > 0)).then((value) => {
4323
- if (!current) return;
4324
- setTodaySpend(value);
4325
- }, () => {});
4331
+ const sessionSpendRequest = fetchLine(isCurrent, () => getSessionSpend(sessionId), setSpend);
4332
+ const todaySpendRequest = fetchLine(isCurrent, () => getTodaySpend(request > 0), setTodaySpend);
4326
4333
  Promise.allSettled([
4327
4334
  balanceRequest,
4328
4335
  sessionSpendRequest,
@@ -4346,17 +4353,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4346
4353
  pricedRunningRef.current = running;
4347
4354
  if (running) return;
4348
4355
  let current = true;
4356
+ const isCurrent = () => current;
4349
4357
  const timer = setTimeout(() => {
4350
- Promise.resolve().then(() => {
4351
- Promise.resolve().then(() => getSessionSpend(sessionId)).then((value) => {
4352
- if (!current) return;
4353
- setSpend(value);
4354
- }, () => {});
4355
- Promise.resolve().then(() => getTodaySpend()).then((value) => {
4356
- if (!current) return;
4357
- setTodaySpend(value);
4358
- }, () => {});
4359
- });
4358
+ fetchLine(isCurrent, () => getSessionSpend(sessionId), setSpend);
4359
+ fetchLine(isCurrent, () => getTodaySpend(), setTodaySpend);
4360
4360
  }, 2e3);
4361
4361
  return () => {
4362
4362
  clearTimeout(timer);
@@ -4542,6 +4542,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4542
4542
  "locale",
4543
4543
  "remote"
4544
4544
  ];
4545
+ /** Unwrap one Remote result into its value, reporting the endpoint on failure. */
4546
+ function unwrap(endpoint, result) {
4547
+ if (!result.ok) throw new Error(`${endpoint} failed: ${result.error.code}: ${result.error.message}`);
4548
+ return result.value;
4549
+ }
4545
4550
  /**
4546
4551
  * Client plugin body: mount the `billing` Remote, register the dictionaries,
4547
4552
  * and contribute the header utility badge.
@@ -4555,29 +4560,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4555
4560
  zh,
4556
4561
  en
4557
4562
  }), "ui-billing: dictionaries");
4558
- const injected = () => ({
4559
- getBalance: async () => {
4560
- const result = await billing.getBalance();
4561
- if (!result.ok) throw new Error(`billing.getBalance failed: ${result.error.code}: ${result.error.message}`);
4562
- return result.value;
4563
- },
4564
- getSessionSpend: async (sessionId) => {
4565
- const result = await billing.getSessionSpend(sessionId);
4566
- if (!result.ok) throw new Error(`billing.getSessionSpend failed: ${result.error.code}: ${result.error.message}`);
4567
- return result.value;
4568
- },
4569
- getTodaySpend: async (force) => {
4570
- const result = await billing.getTodaySpend(force);
4571
- if (!result.ok) throw new Error(`billing.getTodaySpend failed: ${result.error.code}: ${result.error.message}`);
4572
- return result.value;
4573
- }
4574
- });
4563
+ const injected = {
4564
+ getBalance: async () => unwrap("billing.getBalance", await billing.getBalance()),
4565
+ getSessionSpend: async (sessionId) => unwrap("billing.getSessionSpend", await billing.getSessionSpend(sessionId)),
4566
+ getTodaySpend: async (force) => unwrap("billing.getTodaySpend", await billing.getTodaySpend(force))
4567
+ };
4575
4568
  ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
4576
4569
  name: "conversation.session.header.utilities",
4577
4570
  id: "billing-balance",
4578
4571
  order: 30,
4579
4572
  locale: NS,
4580
- inject: injected
4573
+ inject: () => injected
4581
4574
  }, BalanceBadge));
4582
4575
  }
4583
4576
  //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rayadesu/dsh-client-ui-billing",
3
3
  "description": "Session-header DeepSeek account-balance and conversation-spend badge over the billing Remote",
4
- "version": "0.2.2",
4
+ "version": "0.2.3",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",
@@ -47,7 +47,7 @@
47
47
  "access": "public"
48
48
  },
49
49
  "peerDependencies": {
50
- "@rayadesu/dsh-llm-billing": "^0.2.2",
50
+ "@rayadesu/dsh-llm-billing": "^0.2.3",
51
51
  "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
52
52
  "@deepseek-ai/dsh-client-ui-conversation": "^0.1.1-rc.2",
53
53
  "@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.2",
@@ -58,7 +58,7 @@
58
58
  "@deepseek-ai/dsh-session": "^0.1.1-rc.2"
59
59
  },
60
60
  "devDependencies": {
61
- "@rayadesu/dsh-llm-billing": "^0.2.2",
61
+ "@rayadesu/dsh-llm-billing": "^0.2.3",
62
62
  "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
63
63
  "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
64
64
  "@deepseek-ai/dsh-client-test-runtime": "^0.1.1-rc.2",