@jxgame2020/dsh-token-quota 0.1.18 → 0.1.20
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 +11 -3
- package/lib/client.js +97 -90
- package/lib/index.js +48 -49
- package/lib/types/bound-test.d.ts +2 -0
- package/lib/types/bound-test.js +5 -0
- package/lib/types/client/TokenQuotaPanel.d.ts +1 -1
- package/lib/types/client/bound-test.d.ts +2 -0
- package/lib/types/client/bound-test.js +7 -0
- package/lib/types/client/import-test.d.ts +2 -0
- package/lib/types/client/import-test.js +3 -0
- package/lib/types/client/index.d.ts +2 -2
- package/lib/types/client/index.js +28 -14
- package/lib/types/client/store.d.ts +2 -2
- package/lib/types/client/store.js +1 -1
- package/lib/types/import-test.d.ts +2 -0
- package/lib/types/import-test.js +3 -0
- package/lib/types/index.js +58 -54
- package/package.json +29 -10
package/README.md
CHANGED
|
@@ -28,6 +28,10 @@ Zero changes to the DSH core repo: no core file is modified, no official bundle
|
|
|
28
28
|
|
|
29
29
|
## 安装 / Installation
|
|
30
30
|
|
|
31
|
+
> **版本要求 / Version requirement**:`0.1.19+` 需要 DSH **≥ 0.1.5**(新 API:`SettingsProvider.installSection`、`ctx.remote.session`)。DSH 0.1.0-rc.7 及更早版本请使用 `@jxgame2020/dsh-token-quota@0.1.18`。
|
|
32
|
+
>
|
|
33
|
+
> **Version requirement**: `0.1.19+` requires DSH **≥ 0.1.5** (new APIs: `SettingsProvider.installSection`, `ctx.remote.session`). For DSH 0.1.0-rc.7 and earlier, install `@jxgame2020/dsh-token-quota@0.1.18`.
|
|
34
|
+
|
|
31
35
|
### 方式一:npm 安装(推荐)/ Option A: npm install (recommended)
|
|
32
36
|
|
|
33
37
|
在你的 web profile(`~/.dsh/profiles/web`)下安装依赖:
|
|
@@ -36,11 +40,15 @@ Install the dependency in your web profile (`~/.dsh/profiles/web`):
|
|
|
36
40
|
|
|
37
41
|
```bash
|
|
38
42
|
cd ~/.dsh/profiles/web
|
|
39
|
-
npm install @jxgame2020/dsh-token-quota
|
|
43
|
+
npm install @jxgame2020/dsh-token-quota --omit=peer
|
|
40
44
|
```
|
|
41
45
|
|
|
42
|
-
>
|
|
43
|
-
>
|
|
46
|
+
> **为什么 `--omit=peer` / Why `--omit=peer`**:插件运行时所需的 `@deepseek-ai/*` 由 DSH 宿主提供,不需要安装在 profile 里;npm 上这些包的最新 tag 是互不兼容的旧 rc 版本,自动安装 peer 会触发 ERESOLVE 冲突。0.1.20+ 已将这些 peer 全部标记为 optional,直接 `npm install @jxgame2020/dsh-token-quota` 通常也能成功;若仍报 `ERESOLVE`,加上 `--omit=peer` 即可。
|
|
47
|
+
>
|
|
48
|
+
> The plugin's `@deepseek-ai/*` dependencies are provided by the DSH host at runtime — they must NOT be installed into the profile (npm's latest tags for them are mutually-incompatible old rc versions, so auto-installing peers raises ERESOLVE). Since 0.1.20 all those peers are marked optional, so plain `npm install` usually works; if you still hit `ERESOLVE`, append `--omit=peer`.
|
|
49
|
+
|
|
50
|
+
> 用 pnpm 管理 profile 的话:`pnpm add @jxgame2020/dsh-token-quota`(pnpm 默认不装 peer,无需额外参数)。
|
|
51
|
+
> With pnpm: `pnpm add @jxgame2020/dsh-token-quota` (pnpm does not auto-install peers — no extra flag needed).
|
|
44
52
|
|
|
45
53
|
在 `cordis.patch.yml` 中挂载插件:
|
|
46
54
|
|
package/lib/client.js
CHANGED
|
@@ -4,7 +4,7 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
let
|
|
7
|
+
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let react = require("react");
|
|
10
10
|
//#region lib/types/client/store.js
|
|
@@ -26,7 +26,7 @@ window.__ModuleLoader__.load({
|
|
|
26
26
|
* @returns the store handle.
|
|
27
27
|
*/
|
|
28
28
|
function createTokenQuotaPanelStore() {
|
|
29
|
-
return (0,
|
|
29
|
+
return (0, _deepseek_ai_dsh_client_store.defineStore)({
|
|
30
30
|
init: () => ({
|
|
31
31
|
snapshot: null,
|
|
32
32
|
groups: [],
|
|
@@ -79,7 +79,7 @@ window.__ModuleLoader__.load({
|
|
|
79
79
|
d.dimWhenIdle = dimWhenIdle;
|
|
80
80
|
},
|
|
81
81
|
setUpgrade: (d, upgrade) => {
|
|
82
|
-
const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.
|
|
82
|
+
const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.19" ? upgrade : null;
|
|
83
83
|
if (d.upgrade === null || d.upgrade.latestVersion !== normalized?.latestVersion) d.upgradeDismissed = false;
|
|
84
84
|
d.upgrade = normalized;
|
|
85
85
|
},
|
|
@@ -185,91 +185,91 @@ window.__ModuleLoader__.load({
|
|
|
185
185
|
document.head.appendChild(tag);
|
|
186
186
|
}
|
|
187
187
|
var TokenQuotaPanel_module_css_default = {
|
|
188
|
-
"
|
|
189
|
-
"
|
|
190
|
-
"
|
|
191
|
-
"
|
|
192
|
-
"
|
|
193
|
-
"rowName": "NPLLIq_rowName",
|
|
194
|
-
"upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
|
|
195
|
-
"dialogHint": "NPLLIq_dialogHint",
|
|
196
|
-
"panelDim": "NPLLIq_panelDim",
|
|
197
|
-
"upgradeHint": "NPLLIq_upgradeHint",
|
|
188
|
+
"panel": "NPLLIq_panel",
|
|
189
|
+
"rowHeader": "NPLLIq_rowHeader",
|
|
190
|
+
"upgradeCommandRow": "NPLLIq_upgradeCommandRow",
|
|
191
|
+
"logToolbar": "NPLLIq_logToolbar",
|
|
192
|
+
"gearBtn": "NPLLIq_gearBtn",
|
|
198
193
|
"logPagerInfo": "NPLLIq_logPagerInfo",
|
|
199
|
-
"
|
|
200
|
-
"
|
|
201
|
-
"
|
|
202
|
-
"
|
|
203
|
-
"
|
|
204
|
-
"
|
|
205
|
-
"
|
|
206
|
-
"
|
|
207
|
-
"copyBtn": "NPLLIq_copyBtn",
|
|
208
|
-
"resetRow": "NPLLIq_resetRow",
|
|
194
|
+
"fillWarn": "NPLLIq_fillWarn",
|
|
195
|
+
"headerText": "NPLLIq_headerText",
|
|
196
|
+
"dialogLabel": "NPLLIq_dialogLabel",
|
|
197
|
+
"dialogBtn": "NPLLIq_dialogBtn",
|
|
198
|
+
"monitorHint": "NPLLIq_monitorHint",
|
|
199
|
+
"logPagerPages": "NPLLIq_logPagerPages",
|
|
200
|
+
"subtitle": "NPLLIq_subtitle",
|
|
201
|
+
"upgradeCommands": "NPLLIq_upgradeCommands",
|
|
209
202
|
"dialogActions": "NPLLIq_dialogActions",
|
|
203
|
+
"title": "NPLLIq_title",
|
|
210
204
|
"fillOver": "NPLLIq_fillOver",
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
"fillIdle": "NPLLIq_fillIdle",
|
|
214
|
-
"header": "NPLLIq_header",
|
|
215
|
-
"logUsedCol": "NPLLIq_logUsedCol",
|
|
216
|
-
"radioRow": "NPLLIq_radioRow",
|
|
217
|
-
"dialogBtn": "NPLLIq_dialogBtn",
|
|
218
|
-
"body": "NPLLIq_body",
|
|
219
|
-
"monitorName": "NPLLIq_monitorName",
|
|
220
|
-
"dialog": "NPLLIq_dialog",
|
|
221
|
-
"switch": "NPLLIq_switch",
|
|
205
|
+
"monitorRow": "NPLLIq_monitorRow",
|
|
206
|
+
"panelDimStrong": "NPLLIq_panelDimStrong",
|
|
222
207
|
"currentBadge": "NPLLIq_currentBadge",
|
|
223
|
-
"subtitle": "NPLLIq_subtitle",
|
|
224
|
-
"upgradeBanner": "NPLLIq_upgradeBanner",
|
|
225
|
-
"copyBtnDone": "NPLLIq_copyBtnDone",
|
|
226
208
|
"checkUpdatesRow": "NPLLIq_checkUpdatesRow",
|
|
209
|
+
"input": "NPLLIq_input",
|
|
210
|
+
"checkErrorHint": "NPLLIq_checkErrorHint",
|
|
211
|
+
"dialogOverlay": "NPLLIq_dialogOverlay",
|
|
212
|
+
"tabLabel": "NPLLIq_tabLabel",
|
|
213
|
+
"upgradeClose": "NPLLIq_upgradeClose",
|
|
214
|
+
"dialogClose": "NPLLIq_dialogClose",
|
|
227
215
|
"logScroll": "NPLLIq_logScroll",
|
|
228
|
-
"
|
|
229
|
-
"
|
|
216
|
+
"fullNotice": "NPLLIq_fullNotice",
|
|
217
|
+
"settingsBtn": "NPLLIq_settingsBtn",
|
|
218
|
+
"upgradeBanner": "NPLLIq_upgradeBanner",
|
|
219
|
+
"upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
|
|
220
|
+
"logPager": "NPLLIq_logPager",
|
|
230
221
|
"logPageSizeSelect": "NPLLIq_logPageSizeSelect",
|
|
222
|
+
"rowName": "NPLLIq_rowName",
|
|
223
|
+
"logClearDate": "NPLLIq_logClearDate",
|
|
224
|
+
"collapse": "NPLLIq_collapse",
|
|
225
|
+
"bar": "NPLLIq_bar",
|
|
226
|
+
"controls": "NPLLIq_controls",
|
|
227
|
+
"copyBtnDone": "NPLLIq_copyBtnDone",
|
|
228
|
+
"body": "NPLLIq_body",
|
|
229
|
+
"logPagerBtn": "NPLLIq_logPagerBtn",
|
|
230
|
+
"notice": "NPLLIq_notice",
|
|
231
|
+
"monitorName": "NPLLIq_monitorName",
|
|
232
|
+
"logClearBtn": "NPLLIq_logClearBtn",
|
|
233
|
+
"dialogBody": "NPLLIq_dialogBody",
|
|
234
|
+
"resetRow": "NPLLIq_resetRow",
|
|
235
|
+
"dialogHint": "NPLLIq_dialogHint",
|
|
236
|
+
"panelDim": "NPLLIq_panelDim",
|
|
231
237
|
"logDialog": "NPLLIq_logDialog",
|
|
232
|
-
"logDayCol": "NPLLIq_logDayCol",
|
|
233
|
-
"monitorList": "NPLLIq_monitorList",
|
|
234
|
-
"panelDimStrong": "NPLLIq_panelDimStrong",
|
|
235
|
-
"monitorHint": "NPLLIq_monitorHint",
|
|
236
|
-
"logTable": "NPLLIq_logTable",
|
|
237
|
-
"logPager": "NPLLIq_logPager",
|
|
238
|
-
"dialogOverlay": "NPLLIq_dialogOverlay",
|
|
239
|
-
"noticeError": "NPLLIq_noticeError",
|
|
240
238
|
"tab": "NPLLIq_tab",
|
|
241
|
-
"
|
|
242
|
-
"
|
|
243
|
-
"
|
|
244
|
-
"
|
|
239
|
+
"upgradeHint": "NPLLIq_upgradeHint",
|
|
240
|
+
"header": "NPLLIq_header",
|
|
241
|
+
"switch": "NPLLIq_switch",
|
|
242
|
+
"noticeError": "NPLLIq_noticeError",
|
|
245
243
|
"upgradeCommand": "NPLLIq_upgradeCommand",
|
|
244
|
+
"row": "NPLLIq_row",
|
|
245
|
+
"rowMeta": "NPLLIq_rowMeta",
|
|
246
|
+
"checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
|
|
247
|
+
"dialog": "NPLLIq_dialog",
|
|
246
248
|
"dialogHeader": "NPLLIq_dialogHeader",
|
|
247
|
-
"
|
|
249
|
+
"logModelCol": "NPLLIq_logModelCol",
|
|
250
|
+
"logUsedCol": "NPLLIq_logUsedCol",
|
|
248
251
|
"logSearch": "NPLLIq_logSearch",
|
|
249
|
-
"
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
"
|
|
253
|
-
"upgradeCommandRow": "NPLLIq_upgradeCommandRow",
|
|
252
|
+
"logPagerControls": "NPLLIq_logPagerControls",
|
|
253
|
+
"fillIdle": "NPLLIq_fillIdle",
|
|
254
|
+
"monitorList": "NPLLIq_monitorList",
|
|
255
|
+
"upgradeBannerText": "NPLLIq_upgradeBannerText",
|
|
254
256
|
"dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
|
|
255
|
-
"logPagerBtn": "NPLLIq_logPagerBtn",
|
|
256
|
-
"panel": "NPLLIq_panel",
|
|
257
257
|
"version": "NPLLIq_version",
|
|
258
|
-
"upgradeClose": "NPLLIq_upgradeClose",
|
|
259
|
-
"headerText": "NPLLIq_headerText",
|
|
260
|
-
"fullNotice": "NPLLIq_fullNotice",
|
|
261
|
-
"logPagerPages": "NPLLIq_logPagerPages",
|
|
262
|
-
"headerActions": "NPLLIq_headerActions",
|
|
263
|
-
"rowHeader": "NPLLIq_rowHeader",
|
|
264
|
-
"bar": "NPLLIq_bar",
|
|
265
258
|
"dialogTitle": "NPLLIq_dialogTitle",
|
|
266
|
-
"
|
|
267
|
-
"gearBtn": "NPLLIq_gearBtn",
|
|
268
|
-
"monitorRow": "NPLLIq_monitorRow",
|
|
259
|
+
"dialogSection": "NPLLIq_dialogSection",
|
|
269
260
|
"checkBtn": "NPLLIq_checkBtn",
|
|
270
|
-
"
|
|
271
|
-
"
|
|
272
|
-
"
|
|
261
|
+
"save": "NPLLIq_save",
|
|
262
|
+
"selectBtn": "NPLLIq_selectBtn",
|
|
263
|
+
"logDayCol": "NPLLIq_logDayCol",
|
|
264
|
+
"resetSelect": "NPLLIq_resetSelect",
|
|
265
|
+
"copyBtn": "NPLLIq_copyBtn",
|
|
266
|
+
"logClearDialog": "NPLLIq_logClearDialog",
|
|
267
|
+
"radioRow": "NPLLIq_radioRow",
|
|
268
|
+
"versionNew": "NPLLIq_versionNew",
|
|
269
|
+
"tabIcon": "NPLLIq_tabIcon",
|
|
270
|
+
"logTable": "NPLLIq_logTable",
|
|
271
|
+
"logHeader": "NPLLIq_logHeader",
|
|
272
|
+
"headerActions": "NPLLIq_headerActions"
|
|
273
273
|
};
|
|
274
274
|
//#endregion
|
|
275
275
|
//#region lib/types/client/TokenQuotaPanel.js
|
|
@@ -411,8 +411,7 @@ window.__ModuleLoader__.load({
|
|
|
411
411
|
(0, react.useEffect)(() => {
|
|
412
412
|
const onFocusIn = (event) => {
|
|
413
413
|
const target = event.target;
|
|
414
|
-
|
|
415
|
-
setInputActive(isInput);
|
|
414
|
+
setInputActive(target !== null && (target.matches("input, textarea, [contenteditable=\"true\"]") || target.closest("input, textarea, [contenteditable=\"true\"]") !== null));
|
|
416
415
|
};
|
|
417
416
|
window.addEventListener("focusin", onFocusIn);
|
|
418
417
|
return () => {
|
|
@@ -572,13 +571,13 @@ window.__ModuleLoader__.load({
|
|
|
572
571
|
title: t("upgradeAvailableHint"),
|
|
573
572
|
children: [
|
|
574
573
|
"v",
|
|
575
|
-
"0.1.
|
|
574
|
+
"0.1.19",
|
|
576
575
|
" → v",
|
|
577
576
|
upgrade.latestVersion
|
|
578
577
|
]
|
|
579
578
|
}) : (0, react_jsx_runtime.jsxs)("span", {
|
|
580
579
|
className: TokenQuotaPanel_module_css_default.version,
|
|
581
|
-
children: ["v", "0.1.
|
|
580
|
+
children: ["v", "0.1.19"]
|
|
582
581
|
})]
|
|
583
582
|
}), (0, react_jsx_runtime.jsx)("div", {
|
|
584
583
|
className: TokenQuotaPanel_module_css_default.subtitle,
|
|
@@ -1279,10 +1278,10 @@ window.__ModuleLoader__.load({
|
|
|
1279
1278
|
const TOKEN_QUOTA_NAMESPACE = "token-quota";
|
|
1280
1279
|
/** Snapshot pull cadence in milliseconds. */
|
|
1281
1280
|
const POLL_INTERVAL_MS = 3e3;
|
|
1282
|
-
/** Required services: slot registry,
|
|
1281
|
+
/** Required services: slot registry, sessions, locale, settings scope. */
|
|
1283
1282
|
const inject = [
|
|
1284
1283
|
"slots",
|
|
1285
|
-
"
|
|
1284
|
+
"sessions",
|
|
1286
1285
|
"locale",
|
|
1287
1286
|
"settingsScope"
|
|
1288
1287
|
];
|
|
@@ -1299,7 +1298,7 @@ window.__ModuleLoader__.load({
|
|
|
1299
1298
|
}), "token-quota-ui: panel dictionaries");
|
|
1300
1299
|
const t = ctx.locale.bind(NS);
|
|
1301
1300
|
const scope = ctx.settingsScope.bind({ namespace: TOKEN_QUOTA_NAMESPACE });
|
|
1302
|
-
const
|
|
1301
|
+
const sessions = ctx.get("sessions");
|
|
1303
1302
|
const store = createTokenQuotaPanelStore();
|
|
1304
1303
|
let bound;
|
|
1305
1304
|
let lastGroups = [];
|
|
@@ -1366,11 +1365,11 @@ window.__ModuleLoader__.load({
|
|
|
1366
1365
|
bound?.setFullNotice(t("fullSwitchFailed"));
|
|
1367
1366
|
return;
|
|
1368
1367
|
}
|
|
1369
|
-
|
|
1368
|
+
ctx.remote.session.selectModel({
|
|
1370
1369
|
sessionId: lastSessionId,
|
|
1371
1370
|
provider: target.provider,
|
|
1372
1371
|
model: target.model
|
|
1373
|
-
}).then((
|
|
1372
|
+
}).then((result) => {
|
|
1374
1373
|
if (result.ok) {
|
|
1375
1374
|
lastCurrent = result.value.selected;
|
|
1376
1375
|
flashFullNotice(t("fullSwitchTo").replace("{model}", target.model));
|
|
@@ -1381,14 +1380,21 @@ window.__ModuleLoader__.load({
|
|
|
1381
1380
|
});
|
|
1382
1381
|
};
|
|
1383
1382
|
let pullCount = 0;
|
|
1383
|
+
/** Resolve the session's current model from its durable modelSelection projection. */
|
|
1384
|
+
const currentOf = (sessionId) => {
|
|
1385
|
+
const binding = sessions.binding(sessionId);
|
|
1386
|
+
if (binding === void 0) return null;
|
|
1387
|
+
return binding.session.projections.faceOf("modelSelection").getSnapshot()?.lastUsed ?? null;
|
|
1388
|
+
};
|
|
1384
1389
|
const refreshCurrent = () => {
|
|
1385
1390
|
if (lastSessionId === void 0) return;
|
|
1386
|
-
|
|
1391
|
+
ctx.remote.session.modelCatalog().then((result) => {
|
|
1387
1392
|
if (result.ok) {
|
|
1388
|
-
const
|
|
1393
|
+
const current = currentOf(lastSessionId);
|
|
1394
|
+
const currentChanged = lastCurrent?.provider !== current?.provider || lastCurrent?.model !== current?.model;
|
|
1389
1395
|
lastGroups = result.value.groups;
|
|
1390
|
-
lastCurrent =
|
|
1391
|
-
bound?.setDirectory(result.value.groups,
|
|
1396
|
+
lastCurrent = current;
|
|
1397
|
+
bound?.setDirectory(result.value.groups, current);
|
|
1392
1398
|
if (currentChanged) fetch("/token-quota", { headers: { accept: "application/json" } }).then((response) => response.ok ? response.json() : void 0, () => void 0).then((snapshot) => {
|
|
1393
1399
|
if (snapshot !== void 0) {
|
|
1394
1400
|
bound?.setSnapshot(snapshot);
|
|
@@ -1437,11 +1443,12 @@ window.__ModuleLoader__.load({
|
|
|
1437
1443
|
lastSessionId = sessionId;
|
|
1438
1444
|
bound?.setLoading(true);
|
|
1439
1445
|
bound?.setError(null);
|
|
1440
|
-
|
|
1446
|
+
ctx.remote.session.modelCatalog().then((result) => {
|
|
1441
1447
|
if (result.ok) {
|
|
1448
|
+
const current = currentOf(sessionId);
|
|
1442
1449
|
lastGroups = result.value.groups;
|
|
1443
|
-
lastCurrent =
|
|
1444
|
-
bound?.setDirectory(result.value.groups,
|
|
1450
|
+
lastCurrent = current;
|
|
1451
|
+
bound?.setDirectory(result.value.groups, current);
|
|
1445
1452
|
bound?.setLoading(false);
|
|
1446
1453
|
} else {
|
|
1447
1454
|
bound?.setError(`${result.error.code}: ${result.error.message}`);
|
|
@@ -1512,11 +1519,11 @@ window.__ModuleLoader__.load({
|
|
|
1512
1519
|
scope.set("reset", reset);
|
|
1513
1520
|
};
|
|
1514
1521
|
const selectModel = (sessionId, provider, model) => {
|
|
1515
|
-
|
|
1522
|
+
ctx.remote.session.selectModel({
|
|
1516
1523
|
sessionId,
|
|
1517
1524
|
provider,
|
|
1518
1525
|
model
|
|
1519
|
-
}).then((
|
|
1526
|
+
}).then((result) => {
|
|
1520
1527
|
if (result.ok) {
|
|
1521
1528
|
lastCurrent = result.value.selected;
|
|
1522
1529
|
bound?.setFullNotice(null);
|
package/lib/index.js
CHANGED
|
@@ -6,7 +6,6 @@ import { Service } from "@deepseek-ai/cordis";
|
|
|
6
6
|
import z from "@deepseek-ai/schemastery";
|
|
7
7
|
import "@deepseek-ai/dsh-agent";
|
|
8
8
|
import { LlmError } from "@deepseek-ai/dsh-llm";
|
|
9
|
-
import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
10
9
|
//#region lib/types/types.js
|
|
11
10
|
/**
|
|
12
11
|
* Shared wire/type vocabulary for the daily token-quota plugin.
|
|
@@ -66,7 +65,7 @@ const PACKAGE_NAME = "@jxgame2020/dsh-token-quota";
|
|
|
66
65
|
/** npm registry endpoint for the plugin's latest version. */
|
|
67
66
|
const REGISTRY_LATEST_URL = "https://registry.npmjs.org/@jxgame2020%2Fdsh-token-quota/latest";
|
|
68
67
|
/** How often the Host re-checks for a newer version when update checks are enabled. */
|
|
69
|
-
const UPDATE_CHECK_INTERVAL_MS =
|
|
68
|
+
const UPDATE_CHECK_INTERVAL_MS = 1440 * 60 * 1e3;
|
|
70
69
|
/** Map a detected package manager to its install verb. */
|
|
71
70
|
function installVerb(manager) {
|
|
72
71
|
switch (manager) {
|
|
@@ -146,8 +145,7 @@ function detectManager(dir) {
|
|
|
146
145
|
* `undefined` when no profile declares the plugin (e.g. a bundle-managed mount).
|
|
147
146
|
*/
|
|
148
147
|
function findProfile() {
|
|
149
|
-
const
|
|
150
|
-
const profilesDir = join(home, "profiles");
|
|
148
|
+
const profilesDir = join(process.env.DSH_HOME !== void 0 && process.env.DSH_HOME.trim().length > 0 ? process.env.DSH_HOME : join(homedir(), ".dsh"), "profiles");
|
|
151
149
|
let names;
|
|
152
150
|
try {
|
|
153
151
|
names = readdirSync(profilesDir);
|
|
@@ -235,8 +233,7 @@ function cycleKey(now, reset) {
|
|
|
235
233
|
}
|
|
236
234
|
/** Default counter file under the Harness home (overridable through config). */
|
|
237
235
|
function defaultStoragePath() {
|
|
238
|
-
|
|
239
|
-
return join(home, "token-quota.json");
|
|
236
|
+
return join(process.env.DSH_HOME ?? join(homedir(), ".dsh"), "token-quota.json");
|
|
240
237
|
}
|
|
241
238
|
/** Combined input + output + cache token count of one provider usage report. */
|
|
242
239
|
function usageTokens(usage) {
|
|
@@ -304,49 +301,51 @@ var TokenQuotaService = class TokenQuotaService extends Service {
|
|
|
304
301
|
super(ctx, "tokenQuota");
|
|
305
302
|
this.storagePath = config.storagePath !== void 0 && config.storagePath.length > 0 ? config.storagePath : defaultStoragePath();
|
|
306
303
|
this.load();
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
304
|
+
ctx.inject(["settings"], (settingsCtx) => {
|
|
305
|
+
settingsCtx.settings.installSection(ctx, TOKEN_QUOTA_NAMESPACE, TOKEN_QUOTA_SETTINGS_SCHEMA, { limits: {} }, {
|
|
306
|
+
setSource: (current) => {
|
|
307
|
+
this.settingsSource = () => {
|
|
308
|
+
const doc = current();
|
|
309
|
+
return {
|
|
310
|
+
limits: doc.limits ?? {},
|
|
311
|
+
monitored: doc.monitored ?? [],
|
|
312
|
+
onFull: doc.onFull === "switchPriority" ? "switchAll" : doc.onFull ?? "stop",
|
|
313
|
+
checkUpdates: doc.checkUpdates ?? true,
|
|
314
|
+
dimWhenIdle: doc.dimWhenIdle ?? false,
|
|
315
|
+
reset: doc.reset ?? void 0
|
|
316
|
+
};
|
|
318
317
|
};
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
318
|
+
},
|
|
319
|
+
validate: (value) => {
|
|
320
|
+
for (const [key, limit] of Object.entries(value.limits ?? {})) {
|
|
321
|
+
assertTokenQuotaLimit(limit, key);
|
|
322
|
+
splitTokenQuotaKey(key);
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
onChange: () => {
|
|
326
|
+
const doc = this.settingsSource();
|
|
327
|
+
this.limits = { ...doc.limits };
|
|
328
|
+
this.monitored = doc.monitored !== void 0 && doc.monitored.length > 0 ? new Set(doc.monitored) : void 0;
|
|
329
|
+
this.checkUpdates = doc.checkUpdates;
|
|
330
|
+
this.syncUpdateChecking();
|
|
331
|
+
if (doc.reset !== void 0 && typeof doc.reset === "object" && doc.reset !== null && typeof doc.reset.offsetHours === "number" && typeof doc.reset.hour === "number" && typeof doc.reset.minute === "number") {
|
|
332
|
+
const configured = doc.reset;
|
|
333
|
+
this.reset = {
|
|
334
|
+
offsetHours: Math.max(-12, Math.min(14, Math.round(configured.offsetHours))),
|
|
335
|
+
hour: Math.max(0, Math.min(23, Math.round(configured.hour))),
|
|
336
|
+
minute: Math.max(0, Math.min(59, Math.round(configured.minute)))
|
|
337
|
+
};
|
|
338
|
+
this.rollCycleIfNeeded();
|
|
339
|
+
} else {
|
|
340
|
+
this.reset = {
|
|
341
|
+
offsetHours: localOffsetHours(),
|
|
342
|
+
hour: 0,
|
|
343
|
+
minute: 0
|
|
344
|
+
};
|
|
345
|
+
this.rollCycleIfNeeded();
|
|
346
|
+
}
|
|
348
347
|
}
|
|
349
|
-
}
|
|
348
|
+
});
|
|
350
349
|
});
|
|
351
350
|
this.tryMountRoute();
|
|
352
351
|
if (this.disposeRoute === void 0) this.disposeRouteWatcher = ctx.on("internal/service", (name) => {
|
|
@@ -454,7 +453,7 @@ var TokenQuotaService = class TokenQuotaService extends Service {
|
|
|
454
453
|
return this.upgradeCheck;
|
|
455
454
|
}
|
|
456
455
|
async doRefreshUpgrade() {
|
|
457
|
-
const current = "0.1.
|
|
456
|
+
const current = "0.1.19";
|
|
458
457
|
let latest;
|
|
459
458
|
try {
|
|
460
459
|
const response = await fetch(REGISTRY_LATEST_URL, {
|
|
@@ -550,7 +549,7 @@ var TokenQuotaService = class TokenQuotaService extends Service {
|
|
|
550
549
|
/** Read the current snapshot (also used by tests and inspection). */
|
|
551
550
|
readSnapshot() {
|
|
552
551
|
this.rollCycleIfNeeded();
|
|
553
|
-
const keys =
|
|
552
|
+
const keys = new Set([...Object.keys(this.usage), ...Object.keys(this.limits)]);
|
|
554
553
|
const entries = [];
|
|
555
554
|
for (const key of keys) {
|
|
556
555
|
const parts = this.safeSplit(key);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
-
import type { SessionId } from '@deepseek-ai/dsh-
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
3
|
import type { TokenQuotaFullAction, TokenQuotaReset } from '@jxgame2020/dsh-token-quota/types';
|
|
4
4
|
import type { createTokenQuotaPanelStore } from './store.ts';
|
|
5
5
|
/** Injected business face: data loading and mutations wired in `apply`. */
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* full-quota strategy runs: `stop` shows a notice, the other three
|
|
13
13
|
* auto-switch to a suitable model.
|
|
14
14
|
*/
|
|
15
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
15
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
16
16
|
import { type TokenQuotaKey } from './locales.ts';
|
|
17
17
|
export type { TokenQuotaPanelInjected } from './TokenQuotaPanel.tsx';
|
|
18
18
|
export type { ModelQuotaRow, TokenQuotaPanelState } from './store.ts';
|
|
@@ -24,7 +24,7 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
24
24
|
'token-quota': TokenQuotaKey;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
/** Required services: slot registry,
|
|
27
|
+
/** Required services: slot registry, sessions, locale, settings scope. */
|
|
28
28
|
export declare const inject: string[];
|
|
29
29
|
/**
|
|
30
30
|
* Client plugin body: poll the Host snapshot route, run the full-quota
|
|
@@ -8,8 +8,8 @@ const NS = 'token-quota';
|
|
|
8
8
|
const TOKEN_QUOTA_NAMESPACE = 'token-quota';
|
|
9
9
|
/** Snapshot pull cadence in milliseconds. */
|
|
10
10
|
const POLL_INTERVAL_MS = 3000;
|
|
11
|
-
/** Required services: slot registry,
|
|
12
|
-
export const inject = ['slots', '
|
|
11
|
+
/** Required services: slot registry, sessions, locale, settings scope. */
|
|
12
|
+
export const inject = ['slots', 'sessions', 'locale', 'settingsScope'];
|
|
13
13
|
/**
|
|
14
14
|
* Client plugin body: poll the Host snapshot route, run the full-quota
|
|
15
15
|
* strategy, wire the injected face (directory load, limit write, model
|
|
@@ -20,7 +20,10 @@ export function apply(ctx) {
|
|
|
20
20
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'token-quota-ui: panel dictionaries');
|
|
21
21
|
const t = ctx.locale.bind(NS);
|
|
22
22
|
const scope = ctx.settingsScope.bind({ namespace: TOKEN_QUOTA_NAMESPACE });
|
|
23
|
-
|
|
23
|
+
// The Host `dsh-session` package's `ctx.sessions: SessionStore` merge can
|
|
24
|
+
// shadow the client ISessions face in a combined type-check; the runtime
|
|
25
|
+
// 'sessions' service is the ISessions implementation regardless.
|
|
26
|
+
const sessions = ctx.get('sessions');
|
|
24
27
|
// Store handle shared with the registration; the framework instantiates the
|
|
25
28
|
// live store per entry and hands its bound actions to the inject factory,
|
|
26
29
|
// so the apply-world only ever writes through `bound`.
|
|
@@ -107,11 +110,11 @@ export function apply(ctx) {
|
|
|
107
110
|
bound?.setFullNotice(t('fullSwitchFailed'));
|
|
108
111
|
return;
|
|
109
112
|
}
|
|
110
|
-
void
|
|
113
|
+
void ctx.remote.session.selectModel({
|
|
111
114
|
sessionId: lastSessionId,
|
|
112
115
|
provider: target.provider,
|
|
113
116
|
model: target.model,
|
|
114
|
-
}).then((
|
|
117
|
+
}).then((result) => {
|
|
115
118
|
if (result.ok) {
|
|
116
119
|
lastCurrent = result.value.selected;
|
|
117
120
|
flashFullNotice(t('fullSwitchTo').replace('{model}', target.model));
|
|
@@ -130,16 +133,26 @@ export function apply(ctx) {
|
|
|
130
133
|
// switch on full quota) moves the 「当前」 badge without waiting the full
|
|
131
134
|
// directory-refresh cadence.
|
|
132
135
|
let pullCount = 0;
|
|
136
|
+
/** Resolve the session's current model from its durable modelSelection projection. */
|
|
137
|
+
const currentOf = (sessionId) => {
|
|
138
|
+
const binding = sessions.binding(sessionId);
|
|
139
|
+
if (binding === undefined)
|
|
140
|
+
return null;
|
|
141
|
+
const face = binding.session.projections.faceOf('modelSelection');
|
|
142
|
+
const state = face.getSnapshot();
|
|
143
|
+
return state?.lastUsed ?? null;
|
|
144
|
+
};
|
|
133
145
|
const refreshCurrent = () => {
|
|
134
146
|
if (lastSessionId === undefined)
|
|
135
147
|
return;
|
|
136
|
-
void
|
|
148
|
+
void ctx.remote.session.modelCatalog().then((result) => {
|
|
137
149
|
if (result.ok) {
|
|
138
|
-
const
|
|
139
|
-
|
|
150
|
+
const current = currentOf(lastSessionId);
|
|
151
|
+
const currentChanged = lastCurrent?.provider !== current?.provider
|
|
152
|
+
|| lastCurrent?.model !== current?.model;
|
|
140
153
|
lastGroups = result.value.groups;
|
|
141
|
-
lastCurrent =
|
|
142
|
-
bound?.setDirectory(result.value.groups,
|
|
154
|
+
lastCurrent = current;
|
|
155
|
+
bound?.setDirectory(result.value.groups, current);
|
|
143
156
|
// If the server silently switched to a different model (e.g. the
|
|
144
157
|
// auto-switch on quota exhaustion), re-run the full-quota strategy
|
|
145
158
|
// immediately against the new current model so any further fallback
|
|
@@ -201,11 +214,12 @@ export function apply(ctx) {
|
|
|
201
214
|
lastSessionId = sessionId;
|
|
202
215
|
bound?.setLoading(true);
|
|
203
216
|
bound?.setError(null);
|
|
204
|
-
void
|
|
217
|
+
void ctx.remote.session.modelCatalog().then((result) => {
|
|
205
218
|
if (result.ok) {
|
|
219
|
+
const current = currentOf(sessionId);
|
|
206
220
|
lastGroups = result.value.groups;
|
|
207
|
-
lastCurrent =
|
|
208
|
-
bound?.setDirectory(result.value.groups,
|
|
221
|
+
lastCurrent = current;
|
|
222
|
+
bound?.setDirectory(result.value.groups, current);
|
|
209
223
|
bound?.setLoading(false);
|
|
210
224
|
}
|
|
211
225
|
else {
|
|
@@ -282,7 +296,7 @@ export function apply(ctx) {
|
|
|
282
296
|
void scope.set('reset', reset);
|
|
283
297
|
};
|
|
284
298
|
const selectModel = (sessionId, provider, model) => {
|
|
285
|
-
void
|
|
299
|
+
void ctx.remote.session.selectModel({ sessionId, provider, model }).then((result) => {
|
|
286
300
|
if (result.ok) {
|
|
287
301
|
lastCurrent = result.value.selected;
|
|
288
302
|
// A manual pick clears any leftover auto-switch / exhausted notice.
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module @deepseek-ai/dsh-client-ui-token-quota/client/store
|
|
9
9
|
*/
|
|
10
|
-
import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-
|
|
11
|
-
import type { ModelProviderGroup, ModelSelection } from '@deepseek-ai/dsh-api-
|
|
10
|
+
import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-store';
|
|
11
|
+
import type { ModelProviderGroup, ModelSelection } from '@deepseek-ai/dsh-api-session-controller/types';
|
|
12
12
|
import type { TokenQuotaFullAction, TokenQuotaLog, TokenQuotaReset, TokenQuotaSnapshot, TokenQuotaUpgrade } from '@jxgame2020/dsh-token-quota/types';
|
|
13
13
|
/** One rendered model row: directory identity merged with the quota snapshot. */
|
|
14
14
|
export interface ModelQuotaRow {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module @deepseek-ai/dsh-client-ui-token-quota/client/store
|
|
9
9
|
*/
|
|
10
|
-
import { defineStore } from '@deepseek-ai/dsh-client-
|
|
10
|
+
import { defineStore } from '@deepseek-ai/dsh-client-store';
|
|
11
11
|
/** Build the stable per-model key shared by the counter, settings, and snapshot. */
|
|
12
12
|
function tokenQuotaKey(provider, model) {
|
|
13
13
|
return `${provider}/${model}`;
|
package/lib/types/index.js
CHANGED
|
@@ -38,7 +38,6 @@ import z from '@deepseek-ai/schemastery';
|
|
|
38
38
|
// the service listens to without importing any runtime value.
|
|
39
39
|
import '@deepseek-ai/dsh-agent';
|
|
40
40
|
import { LlmError } from '@deepseek-ai/dsh-llm';
|
|
41
|
-
import { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings';
|
|
42
41
|
import { TOKEN_QUOTA_EXCEEDED_CODE, TOKEN_QUOTA_NAMESPACE, tokenQuotaKey, } from "./types.js";
|
|
43
42
|
import { assertTokenQuotaLimit, splitTokenQuotaKey } from "./invariant.js";
|
|
44
43
|
/** The plugin's package name, used to locate the profile dependency and the registry endpoint. */
|
|
@@ -307,60 +306,65 @@ export class TokenQuotaService extends Service {
|
|
|
307
306
|
: defaultStoragePath();
|
|
308
307
|
this.load();
|
|
309
308
|
// Limits live in the user settings document; the Web panel writes them and
|
|
310
|
-
// the section watcher pushes every change back here.
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
309
|
+
// the section watcher pushes every change back here. DSH 0.1.5 replaced
|
|
310
|
+
// the standalone `installSettingsSection` helper with
|
|
311
|
+
// `SettingsProvider.installSection`, reached through `ctx.inject` so the
|
|
312
|
+
// settings service is guaranteed to be up before registration.
|
|
313
|
+
ctx.inject(['settings'], (settingsCtx) => {
|
|
314
|
+
settingsCtx.settings.installSection(ctx, TOKEN_QUOTA_NAMESPACE, TOKEN_QUOTA_SETTINGS_SCHEMA, { limits: {} }, {
|
|
315
|
+
setSource: (current) => {
|
|
316
|
+
// Normalize the resolved (schema-shaped) document into the plugin's
|
|
317
|
+
// required shape: empty monitored = monitor everything, absent onFull
|
|
318
|
+
// falls back to 'stop'.
|
|
319
|
+
this.settingsSource = () => {
|
|
320
|
+
const doc = current();
|
|
321
|
+
return {
|
|
322
|
+
limits: doc.limits ?? {},
|
|
323
|
+
monitored: doc.monitored ?? [],
|
|
324
|
+
// Legacy `switchPriority` (removed in 0.1.7) maps to `switchAll`:
|
|
325
|
+
// capped models first, then uncapped — both monitored-only.
|
|
326
|
+
onFull: doc.onFull === 'switchPriority' ? 'switchAll' : (doc.onFull ?? 'stop'),
|
|
327
|
+
checkUpdates: doc.checkUpdates ?? true,
|
|
328
|
+
dimWhenIdle: doc.dimWhenIdle ?? false,
|
|
329
|
+
reset: doc.reset ?? undefined,
|
|
330
|
+
};
|
|
327
331
|
};
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
}
|
|
332
|
+
},
|
|
333
|
+
validate: (value) => {
|
|
334
|
+
for (const [key, limit] of Object.entries(value.limits ?? {})) {
|
|
335
|
+
assertTokenQuotaLimit(limit, key);
|
|
336
|
+
splitTokenQuotaKey(key);
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
onChange: () => {
|
|
340
|
+
const doc = this.settingsSource();
|
|
341
|
+
this.limits = { ...doc.limits };
|
|
342
|
+
this.monitored = doc.monitored !== undefined && doc.monitored.length > 0
|
|
343
|
+
? new Set(doc.monitored)
|
|
344
|
+
: undefined;
|
|
345
|
+
this.checkUpdates = doc.checkUpdates;
|
|
346
|
+
this.syncUpdateChecking();
|
|
347
|
+
if (doc.reset !== undefined
|
|
348
|
+
&& typeof doc.reset === 'object'
|
|
349
|
+
&& doc.reset !== null
|
|
350
|
+
&& typeof doc.reset.offsetHours === 'number'
|
|
351
|
+
&& typeof doc.reset.hour === 'number'
|
|
352
|
+
&& typeof doc.reset.minute === 'number') {
|
|
353
|
+
const configured = doc.reset;
|
|
354
|
+
this.reset = {
|
|
355
|
+
offsetHours: Math.max(-12, Math.min(14, Math.round(configured.offsetHours))),
|
|
356
|
+
hour: Math.max(0, Math.min(23, Math.round(configured.hour))),
|
|
357
|
+
minute: Math.max(0, Math.min(59, Math.round(configured.minute))),
|
|
358
|
+
};
|
|
359
|
+
this.rollCycleIfNeeded();
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
// null / malformed (unset) = machine-local midnight — the default.
|
|
363
|
+
this.reset = { offsetHours: localOffsetHours(), hour: 0, minute: 0 };
|
|
364
|
+
this.rollCycleIfNeeded();
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
});
|
|
364
368
|
});
|
|
365
369
|
// Snapshot route: optional — only mounted when a webServer service exists
|
|
366
370
|
// (the Web profile); headless deployments keep the enforcement without it.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jxgame2020/dsh-token-quota",
|
|
3
3
|
"description": "Daily per-model token quota accounting, enforcement, and a floating quota panel for the DeepSeek Harness — a fully self-contained plugin (no core-Harness wiring, no generated RPC contract)",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.20",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
"dsh": {
|
|
32
32
|
"client": {
|
|
33
33
|
"inject": [
|
|
34
|
+
"@deepseek-ai/dsh-api-session-controller",
|
|
34
35
|
"@deepseek-ai/dsh-client-locale",
|
|
35
|
-
"@deepseek-ai/dsh-client-
|
|
36
|
+
"@deepseek-ai/dsh-client-store",
|
|
36
37
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
37
38
|
"@deepseek-ai/dsh-client-ui-slots",
|
|
38
39
|
"@deepseek-ai/dsh-api-remotes"
|
|
@@ -56,28 +57,31 @@
|
|
|
56
57
|
"peerDependencies": {
|
|
57
58
|
"@deepseek-ai/cordis": "*",
|
|
58
59
|
"@deepseek-ai/dsh-agent": "*",
|
|
60
|
+
"@deepseek-ai/dsh-api-gateway": "*",
|
|
59
61
|
"@deepseek-ai/dsh-api-remotes": "*",
|
|
62
|
+
"@deepseek-ai/dsh-api-session-controller": "*",
|
|
63
|
+
"@deepseek-ai/dsh-attachment": "*",
|
|
64
|
+
"@deepseek-ai/dsh-brand": "*",
|
|
60
65
|
"@deepseek-ai/dsh-client-connection": "*",
|
|
61
66
|
"@deepseek-ai/dsh-client-locale": "*",
|
|
62
|
-
"@deepseek-ai/dsh-client-
|
|
67
|
+
"@deepseek-ai/dsh-client-store": "*",
|
|
63
68
|
"@deepseek-ai/dsh-client-ui-layout": "*",
|
|
69
|
+
"@deepseek-ai/dsh-client-ui-renderer": "*",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-session": "*",
|
|
64
71
|
"@deepseek-ai/dsh-client-ui-settings": "*",
|
|
65
72
|
"@deepseek-ai/dsh-client-ui-slots": "*",
|
|
66
73
|
"@deepseek-ai/dsh-invariants": "*",
|
|
74
|
+
"@deepseek-ai/dsh-jobs": "*",
|
|
67
75
|
"@deepseek-ai/dsh-llm": "*",
|
|
68
76
|
"@deepseek-ai/dsh-session": "*",
|
|
69
|
-
"@deepseek-ai/dsh-settings": "*",
|
|
70
|
-
"react": "^18.2.0",
|
|
71
|
-
"@deepseek-ai/dsh-host-apiproxy": "*",
|
|
72
|
-
"@deepseek-ai/dsh-attachment": "*",
|
|
73
|
-
"@deepseek-ai/dsh-brand": "*",
|
|
74
|
-
"@deepseek-ai/dsh-jobs": "*",
|
|
75
77
|
"@deepseek-ai/dsh-session-projection": "*",
|
|
78
|
+
"@deepseek-ai/dsh-settings": "*",
|
|
76
79
|
"@deepseek-ai/dsh-tools": "*",
|
|
77
80
|
"@deepseek-ai/dsh-user-approval": "*",
|
|
78
81
|
"@deepseek-ai/dsh-user-questions": "*",
|
|
79
82
|
"@deepseek-ai/dsh-workspace": "*",
|
|
80
|
-
"@deepseek-ai/schemastery": "*"
|
|
83
|
+
"@deepseek-ai/schemastery": "*",
|
|
84
|
+
"react": "^18.2.0"
|
|
81
85
|
},
|
|
82
86
|
"peerDependenciesMeta": {
|
|
83
87
|
"@deepseek-ai/cordis": {
|
|
@@ -148,6 +152,21 @@
|
|
|
148
152
|
},
|
|
149
153
|
"@deepseek-ai/schemastery": {
|
|
150
154
|
"optional": true
|
|
155
|
+
},
|
|
156
|
+
"@deepseek-ai/dsh-api-gateway": {
|
|
157
|
+
"optional": true
|
|
158
|
+
},
|
|
159
|
+
"@deepseek-ai/dsh-api-session-controller": {
|
|
160
|
+
"optional": true
|
|
161
|
+
},
|
|
162
|
+
"@deepseek-ai/dsh-client-store": {
|
|
163
|
+
"optional": true
|
|
164
|
+
},
|
|
165
|
+
"@deepseek-ai/dsh-client-ui-renderer": {
|
|
166
|
+
"optional": true
|
|
167
|
+
},
|
|
168
|
+
"@deepseek-ai/dsh-client-ui-session": {
|
|
169
|
+
"optional": true
|
|
151
170
|
}
|
|
152
171
|
}
|
|
153
172
|
}
|