@rayadesu/dsh-client-ui-billing 0.1.0 → 0.2.0

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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # last confirmed-consistent state. Both languages carry equal authority; after
3
3
  # editing either side, bring the other along and re-record both hashes with:
4
4
  # git hash-object README.md README.zh.md
5
- README.md: c29d9a4ee0ff5a52e184f6ac6fa512b4bf932733
6
- README.zh.md: 8bfeb0333533b20c386fb3f29039742249ed0165
5
+ README.md: 8672854e338576b027810cbfe8bf1a976ffa0824
6
+ README.zh.md: 6c7e0cbd95094d437535def3f2d5d01d5bc98f6c
package/README.md CHANGED
@@ -12,9 +12,9 @@ The badge is account-level even though the slot is session-scoped: the header ut
12
12
 
13
13
  The spends follow the conversation and the balance stays a manual snapshot:
14
14
 
15
- - **Spends follow new messages** — the component subscribes to the current session's message count through the framework `useSession` seat. When a new message lands, it recomputes this session's spend (`billing/getSessionSpend`) and today's spend (`billing/getTodaySpend`), local pricing passes with no network request, so the spend lines stay live during an ongoing conversation.
15
+ - **Spends follow new messages, debounced** — the component subscribes to the current session's message count through the framework `useSession` seat. When a new message lands, it recomputes this session's spend (`billing/getSessionSpend`) and today's spend (`billing/getTodaySpend`), local pricing passes with no network request, so the spend lines stay live during an ongoing conversation. The recompute is debounced for two seconds, so a burst of messages (a streaming agent turn) prices once instead of once per message; the host-side cache (see `dsh-llm-billing`) then serves the first miss for the rest of the minute.
16
16
  - **Balance is manual** — the account balance is fetched on mount, on session switch, and on the explicit refresh action (`billing/getBalance`). There is no polling and no automatic refetch: the balance line only changes when one of those events happens.
17
- - **Refresh keeps the last values** — an in-flight refresh leaves the previous values on screen, and a failed refresh retains the last good value instead of blanking it.
17
+ - **Refresh keeps the last values** — an in-flight refresh leaves the previous values on screen, and a failed refresh retains the last good value instead of blanking it. The refresh action calls `billing/getTodaySpend(true)`, which bypasses the host-side cache; the message-triggered recompute and the mount/session-switch read use the cached path.
18
18
 
19
19
  ## Model Experience
20
20
 
package/README.zh.md CHANGED
@@ -12,9 +12,9 @@ Web 额度特性的归属方:向 `conversation.session.header.utilities` 贡
12
12
 
13
13
  花费跟随会话、额度保持手动快照:
14
14
 
15
- - **花费随新消息自动更新** —— 组件通过框架 `useSession` 座位订阅当前会话的消息数。每到达一条新消息,就只重算**本会话的花费**(`billing/getSessionSpend`)与**今日共花费**(`billing/getTodaySpend`,纯本地计价、不发网络请求),连续对话时花费行实时跟随。
15
+ - **花费随新消息自动更新(去抖)** —— 组件通过框架 `useSession` 座位订阅当前会话的消息数。每到达一条新消息,就只重算**本会话的花费**(`billing/getSessionSpend`)与**今日共花费**(`billing/getTodaySpend`,纯本地计价、不发网络请求),连续对话时花费行实时跟随。重算有 2 秒去抖,消息突发(流式 agent 回合)只计价一次;宿主侧缓存(见 `dsh-llm-billing`)随后在一分钟内服务首次未命中。
16
16
  - **额度保持手动** —— 账户余额在挂载、切换会话、点刷新按钮时拉取(`billing/getBalance`)。**没有轮询、不会自动重拉**:余额行只在这几个时机变化。
17
- - **刷新保留旧值** —— 刷新在途时旧值留在屏幕上,刷新失败保留上一次有效值,不清空。
17
+ - **刷新保留旧值** —— 刷新在途时旧值留在屏幕上,刷新失败保留上一次有效值,不清空。刷新按钮调用 `billing/getTodaySpend(true)`,绕过宿主侧缓存;消息触发的重算与挂载/切换会话的读取走缓存路径。
18
18
 
19
19
  ## 模型体验
20
20
 
package/lib/client.js CHANGED
@@ -7,7 +7,7 @@ window.__ModuleLoader__.load({
7
7
  let react_jsx_runtime = require("react/jsx-runtime");
8
8
  let react = require("react");
9
9
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
10
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/core.js
10
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
11
11
  var _a$1;
12
12
  function $constructor(name, initializer, params) {
13
13
  function init(inst, def) {
@@ -66,7 +66,7 @@ window.__ModuleLoader__.load({
66
66
  return globalConfig;
67
67
  }
68
68
  //#endregion
69
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/util.js
69
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/util.js
70
70
  function getEnumValues(entries) {
71
71
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
72
72
  return Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
@@ -378,7 +378,7 @@ window.__ModuleLoader__.load({
378
378
  return { ...iss };
379
379
  }
380
380
  //#endregion
381
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/errors.js
381
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/errors.js
382
382
  const initializer$1 = (inst, def) => {
383
383
  inst.name = "$ZodError";
384
384
  Object.defineProperty(inst, "_zod", {
@@ -438,7 +438,7 @@ window.__ModuleLoader__.load({
438
438
  return fieldErrors;
439
439
  }
440
440
  //#endregion
441
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/parse.js
441
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/parse.js
442
442
  const _parse = (_Err) => (schema, value, _ctx, _params) => {
443
443
  const ctx = _ctx ? {
444
444
  ..._ctx,
@@ -552,7 +552,7 @@ window.__ModuleLoader__.load({
552
552
  return _safeParseAsync(_Err)(schema, value, _ctx);
553
553
  };
554
554
  //#endregion
555
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/regexes.js
555
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/regexes.js
556
556
  /**
557
557
  * @deprecated CUID v1 is deprecated by its authors due to information leakage
558
558
  * (timestamps embedded in the id). Use {@link cuid2} instead.
@@ -613,10 +613,11 @@ window.__ModuleLoader__.load({
613
613
  const integer = /^-?\d+$/;
614
614
  const number$1 = /^-?\d+(?:\.\d+)?$/;
615
615
  const boolean$1 = /^(?:true|false)$/i;
616
+ const _undefined$2 = /^undefined$/i;
616
617
  const lowercase = /^[^A-Z]*$/;
617
618
  const uppercase = /^[^a-z]*$/;
618
619
  //#endregion
619
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/checks.js
620
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/checks.js
620
621
  const $ZodCheck = /*@__PURE__*/ $constructor("$ZodCheck", (inst, def) => {
621
622
  var _a;
622
623
  inst._zod ?? (inst._zod = {});
@@ -974,7 +975,7 @@ window.__ModuleLoader__.load({
974
975
  };
975
976
  });
976
977
  //#endregion
977
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/doc.js
978
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/doc.js
978
979
  var Doc = class {
979
980
  constructor(args = []) {
980
981
  this.content = [];
@@ -1005,14 +1006,14 @@ window.__ModuleLoader__.load({
1005
1006
  }
1006
1007
  };
1007
1008
  //#endregion
1008
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/versions.js
1009
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js
1009
1010
  const version = {
1010
1011
  major: 4,
1011
1012
  minor: 4,
1012
1013
  patch: 3
1013
1014
  };
1014
1015
  //#endregion
1015
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/schemas.js
1016
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/schemas.js
1016
1017
  const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
1017
1018
  var _a;
1018
1019
  inst ?? (inst = {});
@@ -1425,6 +1426,22 @@ window.__ModuleLoader__.load({
1425
1426
  return payload;
1426
1427
  };
1427
1428
  });
1429
+ const $ZodUndefined = /*@__PURE__*/ $constructor("$ZodUndefined", (inst, def) => {
1430
+ $ZodType.init(inst, def);
1431
+ inst._zod.pattern = _undefined$2;
1432
+ inst._zod.values = new Set([void 0]);
1433
+ inst._zod.parse = (payload, _ctx) => {
1434
+ const input = payload.value;
1435
+ if (typeof input === "undefined") return payload;
1436
+ payload.issues.push({
1437
+ expected: "undefined",
1438
+ code: "invalid_type",
1439
+ input,
1440
+ inst
1441
+ });
1442
+ return payload;
1443
+ };
1444
+ });
1428
1445
  const $ZodUnknown = /*@__PURE__*/ $constructor("$ZodUnknown", (inst, def) => {
1429
1446
  $ZodType.init(inst, def);
1430
1447
  inst._zod.parse = (payload) => payload;
@@ -1886,6 +1903,24 @@ window.__ModuleLoader__.load({
1886
1903
  return payload;
1887
1904
  };
1888
1905
  });
1906
+ const $ZodLiteral = /*@__PURE__*/ $constructor("$ZodLiteral", (inst, def) => {
1907
+ $ZodType.init(inst, def);
1908
+ if (def.values.length === 0) throw new Error("Cannot create literal schema with no valid values");
1909
+ const values = new Set(def.values);
1910
+ inst._zod.values = values;
1911
+ inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
1912
+ inst._zod.parse = (payload, _ctx) => {
1913
+ const input = payload.value;
1914
+ if (values.has(input)) return payload;
1915
+ payload.issues.push({
1916
+ code: "invalid_value",
1917
+ values: def.values,
1918
+ input,
1919
+ inst
1920
+ });
1921
+ return payload;
1922
+ };
1923
+ });
1889
1924
  const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) => {
1890
1925
  $ZodType.init(inst, def);
1891
1926
  inst._zod.optin = "optional";
@@ -2115,7 +2150,7 @@ window.__ModuleLoader__.load({
2115
2150
  }
2116
2151
  }
2117
2152
  //#endregion
2118
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/registries.js
2153
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/registries.js
2119
2154
  var _a;
2120
2155
  var $ZodRegistry = class {
2121
2156
  constructor() {
@@ -2162,7 +2197,7 @@ window.__ModuleLoader__.load({
2162
2197
  (_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());
2163
2198
  const globalRegistry = globalThis.__zod_globalRegistry;
2164
2199
  //#endregion
2165
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/api.js
2200
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/api.js
2166
2201
  // @__NO_SIDE_EFFECTS__
2167
2202
  function _string(Class, params) {
2168
2203
  return new Class({
@@ -2464,6 +2499,13 @@ window.__ModuleLoader__.load({
2464
2499
  });
2465
2500
  }
2466
2501
  // @__NO_SIDE_EFFECTS__
2502
+ function _undefined$1(Class, params) {
2503
+ return new Class({
2504
+ type: "undefined",
2505
+ ...normalizeParams(params)
2506
+ });
2507
+ }
2508
+ // @__NO_SIDE_EFFECTS__
2467
2509
  function _unknown(Class) {
2468
2510
  return new Class({ type: "unknown" });
2469
2511
  }
@@ -2667,7 +2709,7 @@ window.__ModuleLoader__.load({
2667
2709
  return ch;
2668
2710
  }
2669
2711
  //#endregion
2670
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/to-json-schema.js
2712
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/to-json-schema.js
2671
2713
  function initializeContext(params) {
2672
2714
  let target = params?.target ?? "draft-2020-12";
2673
2715
  if (target === "draft-4") target = "draft-04";
@@ -2960,7 +3002,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
2960
3002
  return finalize(ctx, schema);
2961
3003
  };
2962
3004
  //#endregion
2963
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/core/json-schema-processors.js
3005
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/json-schema-processors.js
2964
3006
  const formatMap = {
2965
3007
  guid: "uuid",
2966
3008
  url: "uri",
@@ -3012,6 +3054,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3012
3054
  const booleanProcessor = (_schema, _ctx, json, _params) => {
3013
3055
  json.type = "boolean";
3014
3056
  };
3057
+ const undefinedProcessor = (_schema, ctx, _json, _params) => {
3058
+ if (ctx.unrepresentable === "throw") throw new Error("Undefined cannot be represented in JSON Schema");
3059
+ };
3015
3060
  const neverProcessor = (_schema, _ctx, json, _params) => {
3016
3061
  json.not = {};
3017
3062
  };
@@ -3022,6 +3067,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3022
3067
  if (values.every((v) => typeof v === "string")) json.type = "string";
3023
3068
  json.enum = values;
3024
3069
  };
3070
+ const literalProcessor = (schema, ctx, json, _params) => {
3071
+ const def = schema._zod.def;
3072
+ const vals = [];
3073
+ for (const val of def.values) if (val === void 0) {
3074
+ if (ctx.unrepresentable === "throw") throw new Error("Literal `undefined` cannot be represented in JSON Schema");
3075
+ } else if (typeof val === "bigint") if (ctx.unrepresentable === "throw") throw new Error("BigInt literals cannot be represented in JSON Schema");
3076
+ else vals.push(Number(val));
3077
+ else vals.push(val);
3078
+ if (vals.length === 0) {} else if (vals.length === 1) {
3079
+ const val = vals[0];
3080
+ json.type = val === null ? "null" : typeof val;
3081
+ if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") json.enum = [val];
3082
+ else json.const = val;
3083
+ } else {
3084
+ if (vals.every((v) => typeof v === "number")) json.type = "number";
3085
+ if (vals.every((v) => typeof v === "string")) json.type = "string";
3086
+ if (vals.every((v) => typeof v === "boolean")) json.type = "boolean";
3087
+ if (vals.every((v) => v === null)) json.type = "null";
3088
+ json.enum = vals;
3089
+ }
3090
+ };
3025
3091
  const customProcessor = (_schema, ctx, _json, _params) => {
3026
3092
  if (ctx.unrepresentable === "throw") throw new Error("Custom types cannot be represented in JSON Schema");
3027
3093
  };
@@ -3168,7 +3234,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3168
3234
  seen.ref = def.innerType;
3169
3235
  };
3170
3236
  //#endregion
3171
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/classic/iso.js
3237
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/iso.js
3172
3238
  const ZodISODateTime = /*@__PURE__*/ $constructor("ZodISODateTime", (inst, def) => {
3173
3239
  $ZodISODateTime.init(inst, def);
3174
3240
  ZodStringFormat.init(inst, def);
@@ -3198,7 +3264,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3198
3264
  return /* @__PURE__ */ _isoDuration(ZodISODuration, params);
3199
3265
  }
3200
3266
  //#endregion
3201
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/classic/errors.js
3267
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/errors.js
3202
3268
  const initializer = (inst, issues) => {
3203
3269
  $ZodError.init(inst, issues);
3204
3270
  inst.name = "ZodError";
@@ -3220,7 +3286,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3220
3286
  };
3221
3287
  const ZodRealError = /*@__PURE__*/ $constructor("ZodError", initializer, { Parent: Error });
3222
3288
  //#endregion
3223
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/classic/parse.js
3289
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/parse.js
3224
3290
  const parse = /* @__PURE__ */ _parse(ZodRealError);
3225
3291
  const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
3226
3292
  const safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -3234,7 +3300,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3234
3300
  const safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
3235
3301
  const safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
3236
3302
  //#endregion
3237
- //#region node_modules/@rayadesu/dsh-llm-billing/node_modules/zod/v4/classic/schemas.js
3303
+ //#region ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js
3238
3304
  const _installedGroups = /* @__PURE__ */ new WeakMap();
3239
3305
  function _installLazyMethods(inst, group, methods) {
3240
3306
  const proto = Object.getPrototypeOf(inst);
@@ -3648,6 +3714,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3648
3714
  function boolean(params) {
3649
3715
  return /* @__PURE__ */ _boolean(ZodBoolean, params);
3650
3716
  }
3717
+ const ZodUndefined = /*@__PURE__*/ $constructor("ZodUndefined", (inst, def) => {
3718
+ $ZodUndefined.init(inst, def);
3719
+ ZodType.init(inst, def);
3720
+ inst._zod.processJSONSchema = (ctx, json, params) => undefinedProcessor(inst, ctx, json, params);
3721
+ });
3722
+ function _undefined(params) {
3723
+ return /* @__PURE__ */ _undefined$1(ZodUndefined, params);
3724
+ }
3651
3725
  const ZodUnknown = /*@__PURE__*/ $constructor("ZodUnknown", (inst, def) => {
3652
3726
  $ZodUnknown.init(inst, def);
3653
3727
  ZodType.init(inst, def);
@@ -3823,6 +3897,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3823
3897
  ...normalizeParams(params)
3824
3898
  });
3825
3899
  }
3900
+ const ZodLiteral = /*@__PURE__*/ $constructor("ZodLiteral", (inst, def) => {
3901
+ $ZodLiteral.init(inst, def);
3902
+ ZodType.init(inst, def);
3903
+ inst._zod.processJSONSchema = (ctx, json, params) => literalProcessor(inst, ctx, json, params);
3904
+ inst.values = new Set(def.values);
3905
+ Object.defineProperty(inst, "value", { get() {
3906
+ if (def.values.length > 1) throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");
3907
+ return def.values[0];
3908
+ } });
3909
+ });
3910
+ function literal(value, params) {
3911
+ return new ZodLiteral({
3912
+ type: "literal",
3913
+ values: Array.isArray(value) ? value : [value],
3914
+ ...normalizeParams(params)
3915
+ });
3916
+ }
3826
3917
  const ZodTransform = /*@__PURE__*/ $constructor("ZodTransform", (inst, def) => {
3827
3918
  $ZodTransform.init(inst, def);
3828
3919
  ZodType.init(inst, def);
@@ -3989,8 +4080,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3989
4080
  return /* @__PURE__ */ _superRefine(fn, params);
3990
4081
  }
3991
4082
  //#endregion
3992
- //#region node_modules/@rayadesu/dsh-llm-billing/lib/typert.remote-client.js
3993
- const _deepseek_ai_dsh_llm_billing_billing_getBalance_result$schema = object({
4083
+ //#region ../../llm/llm-billing/lib/typert.remote-client.js
4084
+ const _rayadesu_dsh_llm_billing_billing_getBalance_result$schema = object({
3994
4085
  "isAvailable": boolean(),
3995
4086
  "lines": array(object({
3996
4087
  "currency": string(),
@@ -3999,8 +4090,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3999
4090
  "toppedUp": string()
4000
4091
  }))
4001
4092
  });
4002
- const _deepseek_ai_dsh_llm_billing_billing_getSessionSpend_parameter_0$schema = intersection(string(), unknown());
4003
- const _deepseek_ai_dsh_llm_billing_billing_getSessionSpend_result$schema = object({
4093
+ const _rayadesu_dsh_llm_billing_billing_getSessionSpend_parameter_0$schema = intersection(string(), unknown());
4094
+ const _rayadesu_dsh_llm_billing_billing_getSessionSpend_result$schema = object({
4004
4095
  "total": number(),
4005
4096
  "models": array(object({
4006
4097
  "model": string(),
@@ -4016,7 +4107,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4016
4107
  "outputCost": number()
4017
4108
  }))
4018
4109
  });
4019
- const _deepseek_ai_dsh_llm_billing_billing_getTodaySpend_result$schema = object({
4110
+ const _rayadesu_dsh_llm_billing_billing_getTodaySpend_parameter_0$schema = union([
4111
+ _undefined(),
4112
+ literal(false),
4113
+ literal(true)
4114
+ ]);
4115
+ const _rayadesu_dsh_llm_billing_billing_getTodaySpend_result$schema = object({
4020
4116
  "total": number(),
4021
4117
  "models": array(object({
4022
4118
  "model": string(),
@@ -4045,11 +4141,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4045
4141
  result: {
4046
4142
  mode: "strict",
4047
4143
  typeSymbol: "@rayadesu/dsh-llm-billing/types#DeepSeekBalance",
4048
- schema: _deepseek_ai_dsh_llm_billing_billing_getBalance_result$schema
4144
+ schema: _rayadesu_dsh_llm_billing_billing_getBalance_result$schema
4049
4145
  },
4050
4146
  sourceLocation: {
4051
4147
  "file": "packages/llm/llm-billing/src/balance.ts",
4052
- "line": 139,
4148
+ "line": 143,
4053
4149
  "column": 3
4054
4150
  }
4055
4151
  },
@@ -4066,17 +4162,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4066
4162
  codec: {
4067
4163
  mode: "strict",
4068
4164
  typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
4069
- schema: _deepseek_ai_dsh_llm_billing_billing_getSessionSpend_parameter_0$schema
4165
+ schema: _rayadesu_dsh_llm_billing_billing_getSessionSpend_parameter_0$schema
4070
4166
  }
4071
4167
  }],
4072
4168
  result: {
4073
4169
  mode: "strict",
4074
4170
  typeSymbol: "@rayadesu/dsh-llm-billing/types#DeepSeekSessionSpend",
4075
- schema: _deepseek_ai_dsh_llm_billing_billing_getSessionSpend_result$schema
4171
+ schema: _rayadesu_dsh_llm_billing_billing_getSessionSpend_result$schema
4076
4172
  },
4077
4173
  sourceLocation: {
4078
4174
  "file": "packages/llm/llm-billing/src/balance.ts",
4079
- "line": 149,
4175
+ "line": 154,
4080
4176
  "column": 3
4081
4177
  }
4082
4178
  },
@@ -4086,23 +4182,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4086
4182
  namespace: "billing",
4087
4183
  method: "getTodaySpend",
4088
4184
  invocation: { kind: "direct" },
4089
- parameters: [],
4185
+ parameters: [{
4186
+ name: "force",
4187
+ wire: "force",
4188
+ source: "json",
4189
+ acceptsUndefined: true,
4190
+ codec: {
4191
+ mode: "strict",
4192
+ typeSymbol: "@rayadesu/dsh-llm-billing#billing/getTodaySpend:force",
4193
+ schema: _rayadesu_dsh_llm_billing_billing_getTodaySpend_parameter_0$schema
4194
+ }
4195
+ }],
4090
4196
  result: {
4091
4197
  mode: "strict",
4092
4198
  typeSymbol: "@rayadesu/dsh-llm-billing/types#DeepSeekTodaySpend",
4093
- schema: _deepseek_ai_dsh_llm_billing_billing_getTodaySpend_result$schema
4199
+ schema: _rayadesu_dsh_llm_billing_billing_getTodaySpend_result$schema
4094
4200
  },
4095
4201
  sourceLocation: {
4096
4202
  "file": "packages/llm/llm-billing/src/balance.ts",
4097
- "line": 159,
4203
+ "line": 167,
4098
4204
  "column": 3
4099
4205
  }
4100
4206
  }
4101
4207
  ]
4102
4208
  };
4103
4209
  //#endregion
4104
- //#region \0dsh-css:D:\code\deepseek-harness\packages\client\ui-billing\src\client\BalanceBadge.module.css.mjs
4105
- const css = ".YAT53G_root{position:relative}.YAT53G_trigger{background:var(--dsw-alias-fill-l2);min-height:32px;color:var(--dsw-alias-label-secondary);cursor:pointer;border:0;border-radius:8px;align-items:center;gap:4px;padding:4px 8px;display:inline-flex}.YAT53G_trigger:hover,.YAT53G_trigger:focus-visible{color:var(--dsw-alias-label-primary)}.YAT53G_trigger svg{transition:transform .12s}.YAT53G_chevronOpen{transform:rotate(180deg)}.YAT53G_triggerLines{text-align:left;flex-direction:column;align-items:flex-start;gap:0;display:flex}.YAT53G_linePrimary{font-variant-numeric:tabular-nums;font-size:12px;line-height:16px}.YAT53G_lineSecondary{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:15px}.YAT53G_unavailable{color:var(--dsw-alias-label-tertiary)}.YAT53G_inlineIcon{color:var(--dsw-alias-label-tertiary);flex:none}.YAT53G_spinning{color:var(--dsw-alias-label-tertiary);flex:none;animation:.8s linear infinite YAT53G_spin}@keyframes YAT53G_spin{to{transform:rotate(360deg)}}.YAT53G_panel{z-index:100;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-menu);width:336px;max-width:min(360px,100vw - 32px);box-shadow:var(--dsw-shadow-lv3);border-radius:12px;flex-direction:column;gap:2px;padding:6px;display:flex;position:absolute;top:calc(100% + 6px);right:0}.YAT53G_amountRow{border-radius:8px;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;display:flex}.YAT53G_amountLabel{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:13px;line-height:18px}.YAT53G_spendRow{border-top:1px solid var(--dsw-alias-border-l2);border-radius:0;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;display:flex}.YAT53G_costRow{align-items:center;padding:2px 8px 6px;display:flex}.YAT53G_costBreakdown{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.YAT53G_amountActions{align-items:center;gap:2px;display:inline-flex}.YAT53G_infoButton,.YAT53G_refreshButton{width:24px;height:24px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.YAT53G_infoButton:hover,.YAT53G_infoButton:focus-visible,.YAT53G_refreshButton:hover,.YAT53G_refreshButton:focus-visible{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-l2)}.YAT53G_modelRow{border-radius:8px;justify-content:space-between;align-items:baseline;gap:8px;padding:6px 8px;display:flex}.YAT53G_modelName{color:var(--dsw-alias-label-secondary);flex:none;font-size:12px;line-height:18px}.YAT53G_tasks{text-align:right;min-width:0;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;overflow-wrap:anywhere;font-size:12px;line-height:18px}";
4210
+ //#region \0dsh-css:C:\Users\admin\Desktop\me\code\deepseek-harness\packages\client\ui-billing\src\client\BalanceBadge.module.css.mjs
4211
+ const css = ".v_-kjq_root{position:relative}.v_-kjq_trigger{background:var(--dsw-alias-fill-l2);min-height:32px;color:var(--dsw-alias-label-secondary);cursor:pointer;border:0;border-radius:8px;align-items:center;gap:4px;padding:4px 8px;display:inline-flex}.v_-kjq_trigger:hover,.v_-kjq_trigger:focus-visible{color:var(--dsw-alias-label-primary)}.v_-kjq_trigger svg{transition:transform .12s}.v_-kjq_chevronOpen{transform:rotate(180deg)}.v_-kjq_triggerLines{text-align:left;flex-direction:column;align-items:flex-start;gap:0;display:flex}.v_-kjq_linePrimary{font-variant-numeric:tabular-nums;font-size:12px;line-height:16px}.v_-kjq_lineSecondary{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:15px}.v_-kjq_unavailable{color:var(--dsw-alias-label-tertiary)}.v_-kjq_inlineIcon{color:var(--dsw-alias-label-tertiary);flex:none}.v_-kjq_spinning{color:var(--dsw-alias-label-tertiary);flex:none;animation:.8s linear infinite v_-kjq_spin}@keyframes v_-kjq_spin{to{transform:rotate(360deg)}}.v_-kjq_panel{z-index:100;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-menu);width:336px;max-width:min(360px,100vw - 32px);box-shadow:var(--dsw-shadow-lv3);border-radius:12px;flex-direction:column;gap:2px;padding:6px;display:flex;position:absolute;top:calc(100% + 6px);right:0}.v_-kjq_amountRow{border-radius:8px;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;display:flex}.v_-kjq_amountLabel{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:13px;line-height:18px}.v_-kjq_spendRow{border-top:1px solid var(--dsw-alias-border-l2);border-radius:0;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;display:flex}.v_-kjq_costRow{align-items:center;padding:2px 8px 6px;display:flex}.v_-kjq_costBreakdown{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:11px;line-height:16px}.v_-kjq_amountActions{align-items:center;gap:2px;display:inline-flex}.v_-kjq_infoButton,.v_-kjq_refreshButton{width:24px;height:24px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.v_-kjq_infoButton:hover,.v_-kjq_infoButton:focus-visible,.v_-kjq_refreshButton:hover,.v_-kjq_refreshButton:focus-visible{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-l2)}.v_-kjq_modelRow{border-radius:8px;justify-content:space-between;align-items:baseline;gap:8px;padding:6px 8px;display:flex}.v_-kjq_modelName{color:var(--dsw-alias-label-secondary);flex:none;font-size:12px;line-height:18px}.v_-kjq_tasks{text-align:right;min-width:0;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;overflow-wrap:anywhere;font-size:12px;line-height:18px}";
4106
4212
  const tagId = "@rayadesu/dsh-client-ui-billing/BalanceBadge.module.css";
4107
4213
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
4108
4214
  const tag = document.createElement("style");
@@ -4112,28 +4218,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4112
4218
  document.head.appendChild(tag);
4113
4219
  }
4114
4220
  var BalanceBadge_module_css_default = {
4115
- "amountActions": "YAT53G_amountActions",
4116
- "amountLabel": "YAT53G_amountLabel",
4117
- "amountRow": "YAT53G_amountRow",
4118
- "chevronOpen": "YAT53G_chevronOpen",
4119
- "costBreakdown": "YAT53G_costBreakdown",
4120
- "costRow": "YAT53G_costRow",
4121
- "infoButton": "YAT53G_infoButton",
4122
- "inlineIcon": "YAT53G_inlineIcon",
4123
- "linePrimary": "YAT53G_linePrimary",
4124
- "lineSecondary": "YAT53G_lineSecondary",
4125
- "modelName": "YAT53G_modelName",
4126
- "modelRow": "YAT53G_modelRow",
4127
- "panel": "YAT53G_panel",
4128
- "refreshButton": "YAT53G_refreshButton",
4129
- "root": "YAT53G_root",
4130
- "spendRow": "YAT53G_spendRow",
4131
- "spin": "YAT53G_spin",
4132
- "spinning": "YAT53G_spinning",
4133
- "tasks": "YAT53G_tasks",
4134
- "trigger": "YAT53G_trigger",
4135
- "triggerLines": "YAT53G_triggerLines",
4136
- "unavailable": "YAT53G_unavailable"
4221
+ "amountActions": "v_-kjq_amountActions",
4222
+ "amountLabel": "v_-kjq_amountLabel",
4223
+ "amountRow": "v_-kjq_amountRow",
4224
+ "chevronOpen": "v_-kjq_chevronOpen",
4225
+ "costBreakdown": "v_-kjq_costBreakdown",
4226
+ "costRow": "v_-kjq_costRow",
4227
+ "infoButton": "v_-kjq_infoButton",
4228
+ "inlineIcon": "v_-kjq_inlineIcon",
4229
+ "linePrimary": "v_-kjq_linePrimary",
4230
+ "lineSecondary": "v_-kjq_lineSecondary",
4231
+ "modelName": "v_-kjq_modelName",
4232
+ "modelRow": "v_-kjq_modelRow",
4233
+ "panel": "v_-kjq_panel",
4234
+ "refreshButton": "v_-kjq_refreshButton",
4235
+ "root": "v_-kjq_root",
4236
+ "spendRow": "v_-kjq_spendRow",
4237
+ "spin": "v_-kjq_spin",
4238
+ "spinning": "v_-kjq_spinning",
4239
+ "tasks": "v_-kjq_tasks",
4240
+ "trigger": "v_-kjq_trigger",
4241
+ "triggerLines": "v_-kjq_triggerLines",
4242
+ "unavailable": "v_-kjq_unavailable"
4137
4243
  };
4138
4244
  //#endregion
4139
4245
  //#region lib/types/client/BalanceBadge.js
@@ -4199,7 +4305,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4199
4305
  if (!current) return;
4200
4306
  setSpend(value);
4201
4307
  }, () => {});
4202
- const todaySpendRequest = Promise.resolve().then(getTodaySpend).then((value) => {
4308
+ const todaySpendRequest = Promise.resolve().then(() => getTodaySpend(request > 0)).then((value) => {
4203
4309
  if (!current) return;
4204
4310
  setTodaySpend(value);
4205
4311
  }, () => {});
@@ -4225,17 +4331,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4225
4331
  if (messageCount === pricedMessageCountRef.current) return;
4226
4332
  pricedMessageCountRef.current = messageCount;
4227
4333
  let current = true;
4228
- Promise.resolve().then(() => {
4229
- Promise.resolve().then(() => getSessionSpend(sessionId)).then((value) => {
4230
- if (!current) return;
4231
- setSpend(value);
4232
- }, () => {});
4233
- Promise.resolve().then(getTodaySpend).then((value) => {
4234
- if (!current) return;
4235
- setTodaySpend(value);
4236
- }, () => {});
4237
- });
4334
+ const timer = setTimeout(() => {
4335
+ Promise.resolve().then(() => {
4336
+ Promise.resolve().then(() => getSessionSpend(sessionId)).then((value) => {
4337
+ if (!current) return;
4338
+ setSpend(value);
4339
+ }, () => {});
4340
+ Promise.resolve().then(() => getTodaySpend()).then((value) => {
4341
+ if (!current) return;
4342
+ setTodaySpend(value);
4343
+ }, () => {});
4344
+ });
4345
+ }, 2e3);
4238
4346
  return () => {
4347
+ clearTimeout(timer);
4239
4348
  current = false;
4240
4349
  };
4241
4350
  }, [
@@ -4442,8 +4551,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4442
4551
  if (!result.ok) throw new Error(`billing.getSessionSpend failed: ${result.error.code}: ${result.error.message}`);
4443
4552
  return result.value;
4444
4553
  },
4445
- getTodaySpend: async () => {
4446
- const result = await billing.getTodaySpend();
4554
+ getTodaySpend: async (force) => {
4555
+ const result = await billing.getTodaySpend(force);
4447
4556
  if (!result.ok) throw new Error(`billing.getTodaySpend failed: ${result.error.code}: ${result.error.message}`);
4448
4557
  return result.value;
4449
4558
  }
@@ -9,8 +9,12 @@ export interface BalanceBadgeInjected {
9
9
  getBalance: () => Promise<DeepSeekBalance>;
10
10
  /** Read one session's billed spend; rejects with the Remote error message. */
11
11
  getSessionSpend: (sessionId: SessionId) => Promise<DeepSeekSessionSpend>;
12
- /** Read today's billed spend across every session; rejects with the Remote error message. */
13
- getTodaySpend: () => Promise<DeepSeekTodaySpend>;
12
+ /**
13
+ * Read today's billed spend across every session; rejects with the Remote
14
+ * error message. `force` bypasses the host-side cache — the manual refresh
15
+ * passes it, the message-triggered recompute does not.
16
+ */
17
+ getTodaySpend: (force?: boolean) => Promise<DeepSeekTodaySpend>;
14
18
  }
15
19
  /** Full props assembled by the header utilities slot renderer. */
16
20
  export type BalanceBadgeProps = PropsRuntime<'conversation.session.header.utilities'> & InjectFace<BalanceBadgeInjected> & PropsLocale<typeof NS>;
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.1.0",
4
+ "version": "0.2.0",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "access": "public"
46
46
  },
47
47
  "peerDependencies": {
48
- "@rayadesu/dsh-llm-billing": "^0.1.0",
48
+ "@rayadesu/dsh-llm-billing": "^0.2.0",
49
49
  "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.8",
50
50
  "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.8",
51
51
  "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.8",
@@ -54,7 +54,7 @@
54
54
  "@deepseek-ai/cordis": "^4.0.1"
55
55
  },
56
56
  "devDependencies": {
57
- "@rayadesu/dsh-llm-billing": "^0.1.0",
57
+ "@rayadesu/dsh-llm-billing": "^0.2.0",
58
58
  "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.8",
59
59
  "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.8",
60
60
  "@deepseek-ai/dsh-client-test-runtime": "^0.1.0-rc.8",