dsh-usage-state 0.4.0 → 0.4.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.
- package/README.en.md +1 -0
- package/README.md +1 -0
- package/lib/client.js +76 -39
- package/package.json +3 -1
package/README.en.md
CHANGED
|
@@ -101,6 +101,7 @@ Expanding **Advanced** lets you override the source and endpoint, name a credent
|
|
|
101
101
|
|
|
102
102
|
- **0.2 line only**: `engines.dsh` = `>=0.2.0-rc.2 <0.3.0-0` (this is what dsh-market's badge and install gate read). On an earlier host, install `0.3.2`.
|
|
103
103
|
- `peerDependencies` carry `@deepseek-ai/dsh-settings` (`^0.2.0-rc.2`) and `@deepseek-ai/schemastery` (`^3.18.2`). The first one is deliberate: the runtime install gate only reads `@deepseek-ai/dsh*` peers, so declaring it makes a 0.1.x host **refuse the install** instead of accepting it and then failing to boot. Both are platform-provided; pnpm may print a `missing peer` warning for them, which is expected.
|
|
104
|
+
- Version `0.4.1` fixes `0.4.0`'s missing readings: the browser half's RPC contribution lacked the `create()` factory 0.2 requires, so `remote.usageState` never mounted — the UI showed **no readings at all** and mislabelled the cause as `Mode not supported`. The same release stops swallowing a rejected mount, says "reading" while the catalog is absent, and adds **real 0.2 registry contract tests** (revision 18). **Use `0.4.1`, not `0.4.0`.**
|
|
104
105
|
- Version `0.4.0` migrates to the 0.2 settings model (`Config` + `configForms`, with cross-entry config read through `configEditor`). Verification and results: [`docs/implementation.md`](docs/implementation.md) §10; rationale: [`docs/design-consensus.md`](docs/design-consensus.md) revision 17.
|
|
105
106
|
- Version `0.3.2` (last of the 0.1 line) only widened `engines.dsh`; **its claimed 0.2 compatibility was wrong** — on `0.2.0-rc.2` it fails the entire web boot because `settingsScope` does not exist there.
|
|
106
107
|
- Published to npm as [`dsh-usage-state`](https://www.npmjs.com/package/dsh-usage-state); GitHub installs work too.
|
package/README.md
CHANGED
|
@@ -125,6 +125,7 @@ dsh plugin --profile web add /path/to/dsh-usage-state
|
|
|
125
125
|
|
|
126
126
|
- **只支持 DSH 0.2 线**:`engines.dsh` = `>=0.2.0-rc.2 <0.3.0-0`(市场读它做徽标与"可安装"判定)。0.2 之前的宿主请装 `0.3.2`。
|
|
127
127
|
- `peerDependencies` 里有 `@deepseek-ai/dsh-settings`(`^0.2.0-rc.2`)与 `@deepseek-ai/schemastery`(`^3.18.2`):前者是**故意的**——平台的运行时安装闸门只读 `@deepseek-ai/dsh*` 的 peer,声明它可以让 0.1.x 宿主在**安装时**就拒绝,而不是装上之后把启动搞崩;两者都由平台提供,pnpm 可能为此打一行 `missing peer` 警告,属预期。
|
|
128
|
+
- 版本 `0.4.1`:修 `0.4.0` 的读数缺失——客户端 RPC contribution 的参数 codec 少了 0.2 要求的 `create()`,`remote.usageState` 因此从未挂载,界面表现为**没有任何读数**并误报 `Mode not supported`。同一轮还让挂载失败不再被静默吞掉、catalog 未到时改说「读取中」,并把**真实 0.2 registry 契约测试**写进单测(修订 18)。**请用 `0.4.1`,不要用 `0.4.0`。**
|
|
128
129
|
- 版本 `0.4.0`:迁到 0.2 原生设置模型(`Config` + `configForms`,宿主侧 `configEditor` 读跨条目配置)。验证方式与结论见 [`docs/implementation.md`](docs/implementation.md) §10、决策见 [`docs/design-consensus.md`](docs/design-consensus.md) 修订 17。
|
|
129
130
|
- 版本 `0.3.2`(0.1 线末版):仅放宽 `engines.dsh`;**它声称的 0.2 兼容是错的**(0.3.2 在 0.2.0-rc.2 上会因 `settingsScope` 不存在而让整个 web 启动失败)。
|
|
130
131
|
- 同名发布在 npm([`dsh-usage-state`](https://www.npmjs.com/package/dsh-usage-state)),也可从 GitHub 直接安装。
|
package/lib/client.js
CHANGED
|
@@ -7,6 +7,47 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
|
+
//#region src/client/contribution.ts
|
|
11
|
+
/** Absent or boolean — the one parameter this plugin's RPC takes. */
|
|
12
|
+
const forceSchema = { parse: (value) => value === void 0 ? void 0 : value === true };
|
|
13
|
+
/**
|
|
14
|
+
* A strict codec built without zod: `schema` is what the wire decodes through, and
|
|
15
|
+
* `create()` is the factory the platform's registry calls to obtain it.
|
|
16
|
+
*/
|
|
17
|
+
const booleanOrUndefined = {
|
|
18
|
+
mode: "strict",
|
|
19
|
+
typeSymbol: "dsh-usage-state#Force",
|
|
20
|
+
create: () => forceSchema
|
|
21
|
+
};
|
|
22
|
+
const srcJson = { mode: "src-json" };
|
|
23
|
+
/** Must mirror `src/host/typert.ts`: the wire endpoint is `<namespace>/<method>`. */
|
|
24
|
+
const CONTRIBUTION = {
|
|
25
|
+
package: "dsh-usage-state",
|
|
26
|
+
descriptors: [{
|
|
27
|
+
id: "dsh-usage-state#usageState/getState",
|
|
28
|
+
service: "usageState",
|
|
29
|
+
namespace: "usageState",
|
|
30
|
+
method: "getState",
|
|
31
|
+
invocation: { kind: "direct" },
|
|
32
|
+
parameters: [{
|
|
33
|
+
name: "force",
|
|
34
|
+
wire: "force",
|
|
35
|
+
source: "json",
|
|
36
|
+
acceptsUndefined: true,
|
|
37
|
+
codec: booleanOrUndefined
|
|
38
|
+
}],
|
|
39
|
+
result: srcJson
|
|
40
|
+
}, {
|
|
41
|
+
id: "dsh-usage-state#usageState/describeCredentials",
|
|
42
|
+
service: "usageState",
|
|
43
|
+
namespace: "usageState",
|
|
44
|
+
method: "describeCredentials",
|
|
45
|
+
invocation: { kind: "direct" },
|
|
46
|
+
parameters: [],
|
|
47
|
+
result: srcJson
|
|
48
|
+
}]
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
10
51
|
//#region src/shared/config.ts
|
|
11
52
|
const DEFAULT_CONFIG = {
|
|
12
53
|
models: [],
|
|
@@ -1067,6 +1108,10 @@ window.__ModuleLoader__.load({
|
|
|
1067
1108
|
function describeStatus(input) {
|
|
1068
1109
|
const { status, snapshot, display, now } = input;
|
|
1069
1110
|
if (status.kind === "hidden") return [];
|
|
1111
|
+
if (status.kind === "loading") return [{
|
|
1112
|
+
kind: "state",
|
|
1113
|
+
state: "loading"
|
|
1114
|
+
}];
|
|
1070
1115
|
if (status.kind === "unconfigured") return [{
|
|
1071
1116
|
kind: "state",
|
|
1072
1117
|
state: "unconfigured"
|
|
@@ -1287,12 +1332,15 @@ window.__ModuleLoader__.load({
|
|
|
1287
1332
|
}
|
|
1288
1333
|
}
|
|
1289
1334
|
/** Map a provider resolution onto what the line can say about it. */
|
|
1290
|
-
function statusOf(resolution) {
|
|
1335
|
+
function statusOf(resolution, catalogEmpty) {
|
|
1291
1336
|
switch (resolution.reason) {
|
|
1292
1337
|
case "hidden": return { kind: "hidden" };
|
|
1293
1338
|
case "needs-endpoint": return { kind: "needs-endpoint" };
|
|
1294
1339
|
case "unknown-source":
|
|
1295
|
-
case "unsupported":
|
|
1340
|
+
case "unsupported":
|
|
1341
|
+
if (resolution.sourceId === null) return { kind: "unconfigured" };
|
|
1342
|
+
if (catalogEmpty) return { kind: "loading" };
|
|
1343
|
+
return { kind: "unsupported" };
|
|
1296
1344
|
case "auto":
|
|
1297
1345
|
case "configured":
|
|
1298
1346
|
if (resolution.key === void 0 || resolution.sourceId === null || resolution.mode === null) return { kind: "unconfigured" };
|
|
@@ -1323,11 +1371,15 @@ window.__ModuleLoader__.load({
|
|
|
1323
1371
|
provider: current.provider,
|
|
1324
1372
|
config,
|
|
1325
1373
|
catalog: state.catalog
|
|
1326
|
-
}));
|
|
1374
|
+
}), state.catalog.length === 0);
|
|
1327
1375
|
const snapshot = status.kind === "ready" ? state.snapshots[status.key] : void 0;
|
|
1328
1376
|
const sourceLabel = status.kind === "ready" ? state.catalog.find((entry) => entry.id === status.sourceId)?.displayName ?? status.sourceId : "";
|
|
1329
1377
|
const fullParts = statusParts({
|
|
1330
|
-
segments:
|
|
1378
|
+
segments: state.catalog.length === 0 && state.status === "error" && state.error !== void 0 ? [{
|
|
1379
|
+
kind: "state",
|
|
1380
|
+
state: "error",
|
|
1381
|
+
errorDetail: state.error
|
|
1382
|
+
}] : describeStatus({
|
|
1331
1383
|
sourceLabel,
|
|
1332
1384
|
status,
|
|
1333
1385
|
snapshot,
|
|
@@ -1722,6 +1774,21 @@ window.__ModuleLoader__.load({
|
|
|
1722
1774
|
this.publish({ credentialsError: messageOf(error) });
|
|
1723
1775
|
}
|
|
1724
1776
|
}
|
|
1777
|
+
/**
|
|
1778
|
+
* Record that the RPC contribution never mounted.
|
|
1779
|
+
*
|
|
1780
|
+
* Without this the only symptom is an empty catalog, which every surface reads
|
|
1781
|
+
* as "nothing configured yet" — the real cause has to be nameable, because it is
|
|
1782
|
+
* a plugin/host contract failure, not something the user can configure away.
|
|
1783
|
+
*/
|
|
1784
|
+
failRemote(message) {
|
|
1785
|
+
this.publish({
|
|
1786
|
+
status: "error",
|
|
1787
|
+
error: message,
|
|
1788
|
+
catalog: [],
|
|
1789
|
+
snapshots: {}
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1725
1792
|
};
|
|
1726
1793
|
//#endregion
|
|
1727
1794
|
//#region src/client/index.tsx
|
|
@@ -1735,40 +1802,6 @@ window.__ModuleLoader__.load({
|
|
|
1735
1802
|
];
|
|
1736
1803
|
const USAGE_STATE_NS = "usage-state";
|
|
1737
1804
|
const POLL_INTERVAL_MS = 3e4;
|
|
1738
|
-
/** Hand-rolled codecs: the browser bundle must not carry zod. */
|
|
1739
|
-
const booleanOrUndefined = {
|
|
1740
|
-
mode: "strict",
|
|
1741
|
-
typeSymbol: "dsh-usage-state#Force",
|
|
1742
|
-
schema: { parse: (value) => value === void 0 ? void 0 : value === true }
|
|
1743
|
-
};
|
|
1744
|
-
const srcJson = { mode: "src-json" };
|
|
1745
|
-
/** Must mirror `src/host/typert.ts`: the wire endpoint is `<namespace>/<method>`. */
|
|
1746
|
-
const CONTRIBUTION = {
|
|
1747
|
-
package: "dsh-usage-state",
|
|
1748
|
-
descriptors: [{
|
|
1749
|
-
id: "dsh-usage-state#usageState/getState",
|
|
1750
|
-
service: "usageState",
|
|
1751
|
-
namespace: "usageState",
|
|
1752
|
-
method: "getState",
|
|
1753
|
-
invocation: { kind: "direct" },
|
|
1754
|
-
parameters: [{
|
|
1755
|
-
name: "force",
|
|
1756
|
-
wire: "force",
|
|
1757
|
-
source: "json",
|
|
1758
|
-
acceptsUndefined: true,
|
|
1759
|
-
codec: booleanOrUndefined
|
|
1760
|
-
}],
|
|
1761
|
-
result: srcJson
|
|
1762
|
-
}, {
|
|
1763
|
-
id: "dsh-usage-state#usageState/describeCredentials",
|
|
1764
|
-
service: "usageState",
|
|
1765
|
-
namespace: "usageState",
|
|
1766
|
-
method: "describeCredentials",
|
|
1767
|
-
invocation: { kind: "direct" },
|
|
1768
|
-
parameters: [],
|
|
1769
|
-
result: srcJson
|
|
1770
|
-
}]
|
|
1771
|
-
};
|
|
1772
1805
|
function apply(ctx) {
|
|
1773
1806
|
ctx.effect(() => ctx.locale.register(LOCALE_NS, {
|
|
1774
1807
|
zh,
|
|
@@ -1815,7 +1848,11 @@ window.__ModuleLoader__.load({
|
|
|
1815
1848
|
store.refresh(false);
|
|
1816
1849
|
store.refreshModels();
|
|
1817
1850
|
store.refreshCredentials();
|
|
1818
|
-
}, () =>
|
|
1851
|
+
}, (error) => {
|
|
1852
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1853
|
+
console.error("dsh-usage-state: remote contribution did not mount", error);
|
|
1854
|
+
store.failRemote(message);
|
|
1855
|
+
});
|
|
1819
1856
|
return () => {
|
|
1820
1857
|
cancelled = true;
|
|
1821
1858
|
dispose?.();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-usage-state",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DSH plugin: show account balance (API mode) or coding-plan quota (5h/7d/30d) for the model in use",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,12 +28,14 @@
|
|
|
28
28
|
"./package.json": "./package.json"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
31
32
|
"@deepseek-ai/dsh-client-locale": "^0.2.0-rc.2",
|
|
32
33
|
"@deepseek-ai/dsh-client-store": "^0.2.0-rc.2",
|
|
33
34
|
"@deepseek-ai/dsh-client-ui-conversation": "^0.2.0-rc.2",
|
|
34
35
|
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.0-rc.2",
|
|
35
36
|
"@deepseek-ai/dsh-client-ui-slots": "^0.2.0-rc.2",
|
|
36
37
|
"@deepseek-ai/dsh-typert-loader": "^0.2.0-rc.2",
|
|
38
|
+
"@deepseek-ai/dsh-typert-registry": "^0.2.0-rc.2",
|
|
37
39
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
38
40
|
"@types/node": "^24.0.0",
|
|
39
41
|
"@types/react": "~18.3.1",
|