dsh-ds-balance 2.1.0 → 2.1.2

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.md CHANGED
@@ -1,3 +1,7 @@
1
+ <p align="center">
2
+ <img src="icon.svg" alt="dsh-ds-balance" width="80" height="80">
3
+ </p>
4
+
1
5
  <p align="center">
2
6
  <h1 align="center">dsh-ds-balance</h1>
3
7
  </p>
@@ -40,7 +44,7 @@
40
44
  | 界面 | 一句话 | 你会用它来 |
41
45
  |---|---|---|
42
46
  | 侧栏圆环 | 常驻左边栏底部的状态环 + 名称,**展开态悬浮条目就报出余额金额**,**环里填了多少 = 余额离该币种预警线还有多远** | 扫一眼就知道还剩多少、离预警线多远 |
43
- | 余额浮层 | 点条目展开:总额、赠送 / 充值拆分、数据新鲜度、手动刷新(带冷却);**右上角图标一键跳到插件页** | 核对具体数字,以及数据是几分钟前的 |
47
+ | 余额浮层 | 点条目展开:总额、赠送 / 充值拆分、数据新鲜度、手动刷新(带冷却);**右上角图标跳到本插件的配置格**(宿主没有那条跨插件深链服务时退回 Plugins 列表,悬浮文字同步改口径) | 核对具体数字,以及数据是几分钟前的 |
44
48
  | 设置卡片 | 连接 / 展示 / 阈值 / 刷新四组,**默认四组全收起**,点组头逐组展开 | 换端点、换币种、调预警线、调节奏 |
45
49
 
46
50
  三种界面的分工是死的:**圆环回答「大概还剩多少」,浮层回答「具体是多少」,卡片回答「怎么算」。**
package/README_en.md CHANGED
@@ -1,3 +1,7 @@
1
+ <p align="center">
2
+ <img src="icon.svg" alt="dsh-ds-balance" width="80" height="80">
3
+ </p>
4
+
1
5
  <p align="center">
2
6
  <h1 align="center">dsh-ds-balance</h1>
3
7
  </p>
@@ -40,7 +44,7 @@ The balance needs somewhere to live that does not take up room. A permanent stat
40
44
  | Surface | One line | Use it for |
41
45
  |---|---|---|
42
46
  | Sidebar ring | A status ring plus label at the bottom of the sidebar; **in the expanded state, hovering the entry reports the balance amount**, and **how full it is = how far the balance is from that currency's warning line** | Seeing at a glance how much is left and how close it is to the warning line |
43
- | Balance popover | Click the entry: total, granted / topped-up split, data freshness, manual refresh (with cooldown); **an icon at its top right jumps straight to the Plugins page** | Checking the exact figures, and how many minutes old they are |
47
+ | Balance popover | Click the entry: total, granted / topped-up split, data freshness, manual refresh (with cooldown); **an icon at its top right opens this plugin's configuration page** (on a host without that cross-plugin deep link it falls back to the Plugins list, and its tooltip says so) | Checking the exact figures, and how many minutes old they are |
44
48
  | Settings card | Connection / Display / Thresholds / Refresh, **all collapsed by default**, expand a group from its header | Changing the endpoint, the currency, the warning lines, the cadence |
45
49
 
46
50
  The division of labour is fixed: **the ring answers "roughly how much is left", the popover answers "exactly how much", and the card answers "how is that computed".**
@@ -26,10 +26,18 @@ function render(fields) {
26
26
  */
27
27
  export function createConsoleLogger(sink = console) {
28
28
  return {
29
- debug: (message, fields) => { sink.debug(`${LOG_PREFIX} ${message}${render(fields)}`); },
30
- info: (message, fields) => { sink.info(`${LOG_PREFIX} ${message}${render(fields)}`); },
31
- warn: (message, fields) => { sink.warn(`${LOG_PREFIX} ${message}${render(fields)}`); },
32
- error: (message, fields) => { sink.error(`${LOG_PREFIX} ${message}${render(fields)}`); },
29
+ debug: (message, fields) => {
30
+ sink.debug(`${LOG_PREFIX} ${message}${render(fields)}`);
31
+ },
32
+ info: (message, fields) => {
33
+ sink.info(`${LOG_PREFIX} ${message}${render(fields)}`);
34
+ },
35
+ warn: (message, fields) => {
36
+ sink.warn(`${LOG_PREFIX} ${message}${render(fields)}`);
37
+ },
38
+ error: (message, fields) => {
39
+ sink.error(`${LOG_PREFIX} ${message}${render(fields)}`);
40
+ },
33
41
  };
34
42
  }
35
43
  //# sourceMappingURL=console-logger.js.map
@@ -111,7 +111,9 @@ export class DomainCoreStore {
111
111
  this.ready = null;
112
112
  if (!this.openFailureLogged) {
113
113
  this.openFailureLogged = true;
114
- this.options.logger?.error('ds-balance: storage domain unavailable, running degraded', { error: describeError(error) });
114
+ this.options.logger?.error('ds-balance: storage domain unavailable, running degraded', {
115
+ error: describeError(error),
116
+ });
115
117
  }
116
118
  });
117
119
  this.ready = attempt;
@@ -128,7 +130,9 @@ export class DomainCoreStore {
128
130
  async requireTable() {
129
131
  await this.ensureOpen();
130
132
  if (this.openError !== undefined) {
131
- throw new StorageError(`storage domain unavailable: ${describeError(this.openError)}`, { cause: this.openError });
133
+ throw new StorageError(`storage domain unavailable: ${describeError(this.openError)}`, {
134
+ cause: this.openError,
135
+ });
132
136
  }
133
137
  if (this.table === null)
134
138
  throw new StorageError('storage domain is not open');
@@ -160,7 +164,9 @@ export class DomainCoreStore {
160
164
  if (this.closed)
161
165
  return { ok: false, detail: 'closed' };
162
166
  await this.ensureOpen();
163
- return this.openError === undefined ? { ok: true } : { ok: false, detail: describeError(this.openError) };
167
+ return this.openError === undefined
168
+ ? { ok: true }
169
+ : { ok: false, detail: describeError(this.openError) };
164
170
  }
165
171
  /** 幂等关闭。**必须挂在 `ctx.effect` 的 disposer 上。** */
166
172
  async close() {
@@ -2,7 +2,7 @@
2
2
  * DeepSeek 上游的 HTTP 实现。
3
3
  * @module dsh-ds-balance/adapters/http-deepseek-client
4
4
  */
5
- import { NetworkError, ParseError, TimeoutError, UpstreamError, classify, describeError } from '../domain/errors.js';
5
+ import { NetworkError, ParseError, TimeoutError, UpstreamError, classify, describeError, } from '../domain/errors.js';
6
6
  import { parseErrorBody } from '../domain/normalize.js';
7
7
  /** 去掉尾部斜杠,避免拼出双斜杠路径。 */
8
8
  function joinUrl(baseUrl, path) {
@@ -39,13 +39,21 @@ export class HttpDeepSeekClient {
39
39
  const raw = await this.fetchBalance(options);
40
40
  const latencyMs = this.now() - startedAt;
41
41
  const balances = Array.isArray(raw?.balance_infos)
42
- ? raw.balance_infos.map((item) => ({ currency: String(item.currency), total: String(item.total_balance) }))
42
+ ? raw.balance_infos.map((item) => ({
43
+ currency: String(item.currency),
44
+ total: String(item.total_balance),
45
+ }))
43
46
  : [];
44
47
  return { ok: true, latencyMs, isAvailable: raw?.is_available === true, balances };
45
48
  }
46
49
  catch (error) {
47
50
  const info = classify(error);
48
- return { ok: false, latencyMs: this.now() - startedAt, code: info.code, message: info.message };
51
+ return {
52
+ ok: false,
53
+ latencyMs: this.now() - startedAt,
54
+ code: info.code,
55
+ message: info.message,
56
+ };
49
57
  }
50
58
  }
51
59
  /**
@@ -61,7 +69,9 @@ export class HttpDeepSeekClient {
61
69
  timedOut = true;
62
70
  controller.abort();
63
71
  }, options.timeoutMs);
64
- const forwardAbort = () => { controller.abort(); };
72
+ const forwardAbort = () => {
73
+ controller.abort();
74
+ };
65
75
  options.signal?.addEventListener('abort', forwardAbort, { once: true });
66
76
  let response;
67
77
  try {
@@ -20,8 +20,12 @@ export const SALT_ENCODING = 'hex';
20
20
  */
21
21
  export async function loadOrCreateSalt(options) {
22
22
  const read = options.read ?? (async (path) => readFile(path, 'utf8'));
23
- const write = options.write ?? (async (path, data, mode) => writeFile(path, data, { mode }));
24
- const makeDir = options.makeDir ?? (async (path) => { await mkdir(path, { recursive: true }); });
23
+ const write = options.write ??
24
+ (async (path, data, mode) => writeFile(path, data, { mode }));
25
+ const makeDir = options.makeDir ??
26
+ (async (path) => {
27
+ await mkdir(path, { recursive: true });
28
+ });
25
29
  const random = options.random ?? ((bytes) => randomBytes(bytes).toString(SALT_ENCODING));
26
30
  try {
27
31
  const existing = (await read(options.path)).trim();