dsh-connect-workbuddy 1.1.3 → 1.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/CHANGELOG.md +11 -0
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/lib/bin.js +1 -1
- package/lib/client.js +60 -34
- package/lib/{host-heartbeat-D47UCCoc.js → host-heartbeat-BKokeDPN.js} +1 -1
- package/lib/index.d.ts +23 -1
- package/lib/index.js +34 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0 (2026-09-09)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- **模型选择器显示积分倍率**:DSH 模型选择器中的 WorkBuddy 模型现在按 WorkBuddy 自身选择器的拼写显示积分倍率(如 `GLM-5.3 · x0.79`;未解析到倍率则保持原名称,免费模型显示 `x0.00`)。仅改 DSH 侧显示名(`toPiModel` 与模型 discovery 的 `name`):模型 `id`、`lastCatalog` 存档与插件卡片显示不变——DSH 的选择状态、会话事件(`model/selection` / `request/header`)、agent 默认模型设置与请求路由全部以 `provider + model id` 为连接键,倍率后缀不参与任何映射。
|
|
8
|
+
|
|
9
|
+
### Fixes
|
|
10
|
+
|
|
11
|
+
- **修复模型保存始终失败(`client api: settings/mutate rejected "ops"`)**:卡片保存 `lastCatalog` 时曾用 `nativeContextWindow: undefined, multimodal: undefined` 显式清字段——显式 `undefined` 值会穿过 `structuredClone` 并被设置写入路径的严格 JSON codec 拒绝,导致**整次保存静默失败**(错误是 unhandled rejection,UI 无任何提示;用户侧表现为「保存按钮按不下去」)。姊妹项目 dsh-connect-trae 的 payload 不含 undefined 字段,故不受影响。现在改用 `toPersistedWorkBuddyModel` 按 KEY 剥离卡片专用字段(附回归测试:持久化形状不得含 undefined 值属性、JSON 往返无损)。
|
|
12
|
+
- **保存失败可见化**:保存抛错此前是静默的 unhandled rejection(UI 零提示,正是它掩盖了上一条 bug)。现在保存失败时在按钮旁显示具体原因,草稿保持 dirty 可直接重试;成功路径与 dsh-connect-trae 卡片完全一致(保存中… → 自然结束 → 恢复「保存」并禁用),无额外装饰。
|
|
13
|
+
|
|
3
14
|
## 1.1.3 (2026-09-04)
|
|
4
15
|
|
|
5
16
|
### Breaking Changes
|
package/README.en.md
CHANGED
|
@@ -21,7 +21,7 @@ A [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) bund
|
|
|
21
21
|
|
|
22
22
|
## Features
|
|
23
23
|
|
|
24
|
-
- **WorkBuddy model provider** — registers locally signed-in WorkBuddy models as the `workbuddy` provider (e.g. `GLM-5.3`, `DeepSeek-V4-Pro`, `Kimi-K3`, `MiniMax-M3`, `Hy3`).
|
|
24
|
+
- **WorkBuddy model provider** — registers locally signed-in WorkBuddy models as the `workbuddy` provider (e.g. `GLM-5.3`, `DeepSeek-V4-Pro`, `Kimi-K3`, `MiniMax-M3`, `Hy3`); model names carry the upstream credit multiplier (e.g. `GLM-5.3 · x0.79`), matching WorkBuddy's own model menu.
|
|
25
25
|
- **Model management** — refresh the full catalog from upstream and enable or disable each model individually; refresh is a draft operation that only takes effect on save. Upstream also reports credit multiplier, context/output limits, and reasoning efforts; image input is opted in per model manually (off by default).
|
|
26
26
|
- **Local account switching** — discovers the multiple sign-in credentials WorkBuddy's desktop app leaves behind and lets you switch between them. Tokens are never written to DSH settings.
|
|
27
27
|
- **Read-only credits overview** — remaining credit aggregated per package, plus each model's credit multiplier. Queries consume no credits.
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
## 功能特性
|
|
29
29
|
|
|
30
|
-
- **WorkBuddy 模型接入** —— 把本机登录的 WorkBuddy 模型注册为 DSH 的 `workbuddy` provider,模型选择器出现 `GLM-5.3`、`DeepSeek-V4-Pro`、`Kimi-K3`、`MiniMax-M3`、`Hy3`
|
|
30
|
+
- **WorkBuddy 模型接入** —— 把本机登录的 WorkBuddy 模型注册为 DSH 的 `workbuddy` provider,模型选择器出现 `GLM-5.3`、`DeepSeek-V4-Pro`、`Kimi-K3`、`MiniMax-M3`、`Hy3` 等;模型名内嵌上游积分倍率(如 `GLM-5.3 · x0.79`),与 WorkBuddy 自身模型菜单一致。
|
|
31
31
|
- **模型管理** —— 从上游刷新完整模型目录,逐项勾选启用或禁用;刷新是草稿操作,点保存才生效。上游同时给出积分倍率、上下文/输出上限与推理档位;图片输入按模型手动勾选(默认不勾选)。
|
|
32
32
|
- **本机账号切换** —— 自动发现 WorkBuddy 桌面端留下的多个登录凭据,可切换账号;Token 不写入 DSH 设置。
|
|
33
33
|
- **只读积分概览** —— 按套餐聚合展示剩余积分,并列出每个模型的积分倍率。查询不消耗积分。
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as defaultDesktopAuthCandidates, O as workbuddyOwnAuthPath, a as readHostHeartbeat, b as WORKBUDDY_AUTH_FILE_ENV, c as WORKBUDDY_CONNECT_VERSION, g as FALLBACK_WORKBUDDY_MODELS, l as WorkBuddyUpstreamClient, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, w as defaultDesktopAuthDirs, x as WorkBuddyCredentialStore } from "./host-heartbeat-
|
|
2
|
+
import { C as defaultDesktopAuthCandidates, O as workbuddyOwnAuthPath, a as readHostHeartbeat, b as WORKBUDDY_AUTH_FILE_ENV, c as WORKBUDDY_CONNECT_VERSION, g as FALLBACK_WORKBUDDY_MODELS, l as WorkBuddyUpstreamClient, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, w as defaultDesktopAuthDirs, x as WorkBuddyCredentialStore } from "./host-heartbeat-BKokeDPN.js";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/bin.ts
|
package/lib/client.js
CHANGED
|
@@ -29,6 +29,22 @@ window.__ModuleLoader__.load({
|
|
|
29
29
|
const WORKBUDDY_ACCOUNTS_REFRESH_PATH = "/plugins/dsh-connect-workbuddy/accounts/refresh";
|
|
30
30
|
/** Plugin-owned daily check-in action endpoint. */
|
|
31
31
|
const WORKBUDDY_CHECKIN_PATH = "/plugins/dsh-connect-workbuddy/checkin";
|
|
32
|
+
/**
|
|
33
|
+
* Project one card row into its persisted `lastCatalog` shape: the native
|
|
34
|
+
* context window becomes the stored `contextWindow`, and the card-only
|
|
35
|
+
* presentation fields (`nativeContextWindow`, `multimodal`) are removed BY
|
|
36
|
+
* KEY. They must never be set to `undefined`: explicit `undefined` values
|
|
37
|
+
* survive `structuredClone` and are rejected by the settings write path's
|
|
38
|
+
* strict JSON codec (`client api: settings/mutate rejected "ops"`), which
|
|
39
|
+
* fails the whole save.
|
|
40
|
+
*/
|
|
41
|
+
function toPersistedWorkBuddyModel(model) {
|
|
42
|
+
const { nativeContextWindow, multimodal: _cardOnly, ...rest } = model;
|
|
43
|
+
return {
|
|
44
|
+
...rest,
|
|
45
|
+
contextWindow: nativeContextWindow
|
|
46
|
+
};
|
|
47
|
+
}
|
|
32
48
|
//#endregion
|
|
33
49
|
//#region src/client/icon.ts
|
|
34
50
|
/**
|
|
@@ -142,6 +158,7 @@ window.__ModuleLoader__.load({
|
|
|
142
158
|
.dsm-workbuddy-context-budget input{margin:0;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
143
159
|
.dsm-workbuddy-model-capability-note{margin:0;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
144
160
|
.dsm-workbuddy-model-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--dsw-alias-border-l2,#36373b);padding-top:12px}
|
|
161
|
+
.dsm-workbuddy-model-save-error{flex:1;min-width:0;color:var(--dsw-alias-state-error-primary,#ef4444);font-size:12px;line-height:16px;text-align:right}
|
|
145
162
|
.dsm-workbuddy-model-actions-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px}
|
|
146
163
|
.dsm-workbuddy-usage-cheer{display:inline-flex;align-items:center;gap:4px;flex:none;text-decoration:underline;text-underline-offset:2px;color:var(--dsw-alias-label-tertiary,#999);font-size:13px;line-height:1.5;transition:color .16s}
|
|
147
164
|
.dsm-workbuddy-usage-cheer-star{font-size:12px;line-height:1;display:inline-flex}
|
|
@@ -232,6 +249,8 @@ window.__ModuleLoader__.load({
|
|
|
232
249
|
const [draftImageIds, setDraftImageIds] = (0, react.useState)(void 0);
|
|
233
250
|
const [draftContextBudgets, setDraftContextBudgets] = (0, react.useState)(void 0);
|
|
234
251
|
const [saving, setSaving] = (0, react.useState)(false);
|
|
252
|
+
/** Save failure surfaced next to the buttons; cleared by the next attempt. */
|
|
253
|
+
const [saveError, setSaveError] = (0, react.useState)(void 0);
|
|
235
254
|
const [switchingAccount, setSwitchingAccount] = (0, react.useState)(false);
|
|
236
255
|
const [checkingIn, setCheckingIn] = (0, react.useState)(false);
|
|
237
256
|
const [checkinActionError, setCheckinActionError] = (0, react.useState)(void 0);
|
|
@@ -403,18 +422,16 @@ window.__ModuleLoader__.load({
|
|
|
403
422
|
const saveModels = async () => {
|
|
404
423
|
if (settingsScope === void 0) return;
|
|
405
424
|
setSaving(true);
|
|
425
|
+
setSaveError(void 0);
|
|
406
426
|
try {
|
|
407
|
-
await settingsScope.set("lastCatalog", visibleModels.map(
|
|
408
|
-
...model,
|
|
409
|
-
contextWindow: model.nativeContextWindow,
|
|
410
|
-
nativeContextWindow: void 0,
|
|
411
|
-
multimodal: void 0
|
|
412
|
-
})));
|
|
427
|
+
await settingsScope.set("lastCatalog", visibleModels.map(toPersistedWorkBuddyModel));
|
|
413
428
|
await settingsScope.set("enabledModelIds", [...activeEnabledIds]);
|
|
414
429
|
await settingsScope.set("imageModelIds", [...activeImageIds]);
|
|
415
430
|
await settingsScope.set("contextBudgets", activeContextBudgets);
|
|
416
431
|
discardModels();
|
|
417
432
|
await refreshUsage();
|
|
433
|
+
} catch (error) {
|
|
434
|
+
if (mounted.current) setSaveError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
418
435
|
} finally {
|
|
419
436
|
if (mounted.current) setSaving(false);
|
|
420
437
|
}
|
|
@@ -694,34 +711,41 @@ window.__ModuleLoader__.load({
|
|
|
694
711
|
}),
|
|
695
712
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
696
713
|
className: "dsm-workbuddy-model-actions",
|
|
697
|
-
children: [
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
},
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
714
|
+
children: [
|
|
715
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
716
|
+
className: "dsm-workbuddy-usage-cheer",
|
|
717
|
+
href: WORKBUDDY_GITHUB_URL,
|
|
718
|
+
target: "_blank",
|
|
719
|
+
rel: "noopener noreferrer",
|
|
720
|
+
children: [t("row.cheer"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
721
|
+
className: "dsm-workbuddy-usage-cheer-star",
|
|
722
|
+
"aria-hidden": "true",
|
|
723
|
+
children: "★"
|
|
724
|
+
})]
|
|
725
|
+
}),
|
|
726
|
+
saveError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
727
|
+
className: "dsm-workbuddy-model-save-error",
|
|
728
|
+
children: t("row.saveError", { message: saveError })
|
|
729
|
+
}),
|
|
730
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
731
|
+
className: "dsm-workbuddy-model-actions-buttons",
|
|
732
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
733
|
+
type: "button",
|
|
734
|
+
className: "dsm-btn dsm-btn-outline",
|
|
735
|
+
disabled: !dirty || saving,
|
|
736
|
+
onClick: discardModels,
|
|
737
|
+
children: t("row.discard")
|
|
738
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
739
|
+
type: "button",
|
|
740
|
+
className: "dsm-btn dsm-btn-primary",
|
|
741
|
+
disabled: !dirty || saving || activeEnabledIds.size === 0,
|
|
742
|
+
onClick: () => {
|
|
743
|
+
saveModels();
|
|
744
|
+
},
|
|
745
|
+
children: saving ? t("row.saving") : t("row.save")
|
|
746
|
+
})]
|
|
747
|
+
})
|
|
748
|
+
]
|
|
725
749
|
})
|
|
726
750
|
]
|
|
727
751
|
})
|
|
@@ -785,6 +809,7 @@ window.__ModuleLoader__.load({
|
|
|
785
809
|
"row.discard": "Discard changes",
|
|
786
810
|
"row.save": "Save",
|
|
787
811
|
"row.saving": "Saving…",
|
|
812
|
+
"row.saveError": "Save failed: {message}",
|
|
788
813
|
"row.modelContext": "Maximum context {context}",
|
|
789
814
|
"row.contextBudget": "DSH context budget",
|
|
790
815
|
"row.modelOutput": "Output {output}",
|
|
@@ -829,6 +854,7 @@ window.__ModuleLoader__.load({
|
|
|
829
854
|
"row.discard": "放弃修改",
|
|
830
855
|
"row.save": "保存",
|
|
831
856
|
"row.saving": "保存中…",
|
|
857
|
+
"row.saveError": "保存失败:{message}",
|
|
832
858
|
"row.modelContext": "最大上下文 {context}",
|
|
833
859
|
"row.contextBudget": "DSH 上下文预算",
|
|
834
860
|
"row.modelOutput": "最大输出 {output}",
|
|
@@ -996,7 +996,7 @@ var WorkBuddyUpstreamClient = class {
|
|
|
996
996
|
//#endregion
|
|
997
997
|
//#region src/version.ts
|
|
998
998
|
/** The npm package version this build was produced from. */
|
|
999
|
-
const WORKBUDDY_CONNECT_VERSION = "1.
|
|
999
|
+
const WORKBUDDY_CONNECT_VERSION = "1.2.0";
|
|
1000
1000
|
//#endregion
|
|
1001
1001
|
//#region src/host-heartbeat.ts
|
|
1002
1002
|
/**
|
package/lib/index.d.ts
CHANGED
|
@@ -398,6 +398,18 @@ type WorkBuddyThinkingLevel = typeof THINKING_LEVELS[number];
|
|
|
398
398
|
type WorkBuddyThinkingLevelMap = Partial<Record<'off' | WorkBuddyThinkingLevel, string | null>>;
|
|
399
399
|
/** pi-ai input modalities: images only when WorkBuddy advertises them. */
|
|
400
400
|
declare function workBuddyModelInput(info: WorkBuddyModelInfo): ('text' | 'image')[];
|
|
401
|
+
/**
|
|
402
|
+
* DSH-facing display name: the model name plus the upstream credit multiplier,
|
|
403
|
+
* spelled the way WorkBuddy's own selector does (`GLM-5.3 · x0.79`).
|
|
404
|
+
*
|
|
405
|
+
* Display-only by construction: every DSH-side join keys on the model id —
|
|
406
|
+
* the selector's current choice (`provider` + `model`), the durable
|
|
407
|
+
* `model/selection` / `request/header` session events, the agent default-model
|
|
408
|
+
* settings, and the request wire (`model: <id>` reaching the shim). A model
|
|
409
|
+
* without a parsed multiplier keeps its bare name; a zero multiplier shows
|
|
410
|
+
* `x0.00`, matching WorkBuddy's rendering of free models.
|
|
411
|
+
*/
|
|
412
|
+
declare function workBuddyDisplayName(info: WorkBuddyModelInfo): string;
|
|
401
413
|
/** Map only levels advertised by WorkBuddy; undeclared DSH levels stay unavailable. */
|
|
402
414
|
declare function workBuddyThinkingLevelMap(info: WorkBuddyModelInfo): WorkBuddyThinkingLevelMap | undefined;
|
|
403
415
|
/**
|
|
@@ -546,6 +558,16 @@ interface WorkBuddyWebModel {
|
|
|
546
558
|
};
|
|
547
559
|
description?: string;
|
|
548
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* Project one card row into its persisted `lastCatalog` shape: the native
|
|
563
|
+
* context window becomes the stored `contextWindow`, and the card-only
|
|
564
|
+
* presentation fields (`nativeContextWindow`, `multimodal`) are removed BY
|
|
565
|
+
* KEY. They must never be set to `undefined`: explicit `undefined` values
|
|
566
|
+
* survive `structuredClone` and are rejected by the settings write path's
|
|
567
|
+
* strict JSON codec (`client api: settings/mutate rejected "ops"`), which
|
|
568
|
+
* fails the whole save.
|
|
569
|
+
*/
|
|
570
|
+
declare function toPersistedWorkBuddyModel(model: WorkBuddyWebModel): Omit<WorkBuddyWebModel, 'nativeContextWindow' | 'multimodal'>;
|
|
549
571
|
/** One selectable local account, token-free. */
|
|
550
572
|
interface WorkBuddyWebAccount {
|
|
551
573
|
id: string;
|
|
@@ -643,4 +665,4 @@ declare const Config: z<Config>;
|
|
|
643
665
|
*/
|
|
644
666
|
declare function apply(ctx: Context, config: Config): void;
|
|
645
667
|
//#endregion
|
|
646
|
-
export { Config, FALLBACK_WORKBUDDY_MODELS, type UpstreamErrorKind, WORKBUDDY_ACCOUNTS_REFRESH_PATH, WORKBUDDY_AUTH_FILENAME, WORKBUDDY_AUTH_FILE_ENV, WORKBUDDY_CHECKIN_PATH, WORKBUDDY_CONNECT_VERSION, WORKBUDDY_HOST_HEARTBEAT_FILENAME, WORKBUDDY_MODELS_REFRESH_PATH, WORKBUDDY_PROVIDER, WORKBUDDY_SETTINGS_NS, WORKBUDDY_STREAM_IDLE_TIMEOUT_MS, WORKBUDDY_USAGE_PATH, type WorkBuddyAccountChoice, type WorkBuddyAdapter, type WorkBuddyAuthStatus, WorkBuddyCatalog, type WorkBuddyChatResult, type WorkBuddyCredential, WorkBuddyCredentialStore, type WorkBuddyCreditPackage, type WorkBuddyCredits, type WorkBuddyHostHeartbeat, type WorkBuddyModelInfo, type WorkBuddyReasoning, type WorkBuddyRefreshOutcome, type WorkBuddyShim, type WorkBuddyStatusRouteOptions, type WorkBuddyStoreOptions, WorkBuddyUpstreamClient, type WorkBuddyUpstreamModel, type WorkBuddyWebAccount, type WorkBuddyWebCheckin, type WorkBuddyWebCredits, type WorkBuddyWebModel, type WorkBuddyWebPackage, type WorkBuddyWebUsage, apply, authFileName, classifyUpstreamError, clearHostHeartbeat, createWorkBuddyAdapter, createWorkBuddyShim, defaultDesktopAuthCandidates, defaultDesktopAuthDirs, defaultDesktopAuthPath, deriveCatalog, inject, isHeartbeatProcessAlive, name, parseCreditMultiplier, parseReasoning, parseUpstreamModel, parseWorkBuddyAuth, prepareChatBody, processStartTimeMs, readHostHeartbeat, regionOf, registerWorkBuddyStatusRoute, workBuddyModelInput, workBuddyThinkingLevelMap, workBuddyWebStatus, workbuddyAccountId, workbuddyHostHeartbeatPath, workbuddyOwnAuthPath, writeHostHeartbeat };
|
|
668
|
+
export { Config, FALLBACK_WORKBUDDY_MODELS, type UpstreamErrorKind, WORKBUDDY_ACCOUNTS_REFRESH_PATH, WORKBUDDY_AUTH_FILENAME, WORKBUDDY_AUTH_FILE_ENV, WORKBUDDY_CHECKIN_PATH, WORKBUDDY_CONNECT_VERSION, WORKBUDDY_HOST_HEARTBEAT_FILENAME, WORKBUDDY_MODELS_REFRESH_PATH, WORKBUDDY_PROVIDER, WORKBUDDY_SETTINGS_NS, WORKBUDDY_STREAM_IDLE_TIMEOUT_MS, WORKBUDDY_USAGE_PATH, type WorkBuddyAccountChoice, type WorkBuddyAdapter, type WorkBuddyAuthStatus, WorkBuddyCatalog, type WorkBuddyChatResult, type WorkBuddyCredential, WorkBuddyCredentialStore, type WorkBuddyCreditPackage, type WorkBuddyCredits, type WorkBuddyHostHeartbeat, type WorkBuddyModelInfo, type WorkBuddyReasoning, type WorkBuddyRefreshOutcome, type WorkBuddyShim, type WorkBuddyStatusRouteOptions, type WorkBuddyStoreOptions, WorkBuddyUpstreamClient, type WorkBuddyUpstreamModel, type WorkBuddyWebAccount, type WorkBuddyWebCheckin, type WorkBuddyWebCredits, type WorkBuddyWebModel, type WorkBuddyWebPackage, type WorkBuddyWebUsage, apply, authFileName, classifyUpstreamError, clearHostHeartbeat, createWorkBuddyAdapter, createWorkBuddyShim, defaultDesktopAuthCandidates, defaultDesktopAuthDirs, defaultDesktopAuthPath, deriveCatalog, inject, isHeartbeatProcessAlive, name, parseCreditMultiplier, parseReasoning, parseUpstreamModel, parseWorkBuddyAuth, prepareChatBody, processStartTimeMs, readHostHeartbeat, regionOf, registerWorkBuddyStatusRoute, toPersistedWorkBuddyModel, workBuddyDisplayName, workBuddyModelInput, workBuddyThinkingLevelMap, workBuddyWebStatus, workbuddyAccountId, workbuddyHostHeartbeatPath, workbuddyOwnAuthPath, writeHostHeartbeat };
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as defaultDesktopAuthCandidates, D as workbuddyAccountId, E as parseWorkBuddyAuth, O as workbuddyOwnAuthPath, S as authFileName, T as defaultDesktopAuthPath, _ as WorkBuddyCatalog, a as readHostHeartbeat, b as WORKBUDDY_AUTH_FILE_ENV, c as WORKBUDDY_CONNECT_VERSION, d as parseCreditMultiplier, f as parseReasoning, g as FALLBACK_WORKBUDDY_MODELS, h as regionOf, i as processStartTimeMs, l as WorkBuddyUpstreamClient, m as prepareChatBody, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as parseUpstreamModel, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as classifyUpstreamError, v as deriveCatalog, w as defaultDesktopAuthDirs, x as WorkBuddyCredentialStore, y as WORKBUDDY_AUTH_FILENAME } from "./host-heartbeat-
|
|
1
|
+
import { C as defaultDesktopAuthCandidates, D as workbuddyAccountId, E as parseWorkBuddyAuth, O as workbuddyOwnAuthPath, S as authFileName, T as defaultDesktopAuthPath, _ as WorkBuddyCatalog, a as readHostHeartbeat, b as WORKBUDDY_AUTH_FILE_ENV, c as WORKBUDDY_CONNECT_VERSION, d as parseCreditMultiplier, f as parseReasoning, g as FALLBACK_WORKBUDDY_MODELS, h as regionOf, i as processStartTimeMs, l as WorkBuddyUpstreamClient, m as prepareChatBody, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as parseUpstreamModel, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as classifyUpstreamError, v as deriveCatalog, w as defaultDesktopAuthDirs, x as WorkBuddyCredentialStore, y as WORKBUDDY_AUTH_FILENAME } from "./host-heartbeat-BKokeDPN.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
4
4
|
import { createProvider } from "@earendil-works/pi-ai";
|
|
@@ -80,6 +80,20 @@ const THINKING_LEVELS = [
|
|
|
80
80
|
function workBuddyModelInput(info) {
|
|
81
81
|
return info.multimodal === true ? ["text", "image"] : ["text"];
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* DSH-facing display name: the model name plus the upstream credit multiplier,
|
|
85
|
+
* spelled the way WorkBuddy's own selector does (`GLM-5.3 · x0.79`).
|
|
86
|
+
*
|
|
87
|
+
* Display-only by construction: every DSH-side join keys on the model id —
|
|
88
|
+
* the selector's current choice (`provider` + `model`), the durable
|
|
89
|
+
* `model/selection` / `request/header` session events, the agent default-model
|
|
90
|
+
* settings, and the request wire (`model: <id>` reaching the shim). A model
|
|
91
|
+
* without a parsed multiplier keeps its bare name; a zero multiplier shows
|
|
92
|
+
* `x0.00`, matching WorkBuddy's rendering of free models.
|
|
93
|
+
*/
|
|
94
|
+
function workBuddyDisplayName(info) {
|
|
95
|
+
return info.creditMultiplier === void 0 ? info.name : `${info.name} · x${info.creditMultiplier.toFixed(2)}`;
|
|
96
|
+
}
|
|
83
97
|
/** Map only levels advertised by WorkBuddy; undeclared DSH levels stay unavailable. */
|
|
84
98
|
function workBuddyThinkingLevelMap(info) {
|
|
85
99
|
const supported = info.reasoning?.supportedEfforts?.filter((effort) => THINKING_LEVELS.includes(effort));
|
|
@@ -93,7 +107,7 @@ function toPiModel(info, baseUrl) {
|
|
|
93
107
|
const thinkingLevelMap = workBuddyThinkingLevelMap(info);
|
|
94
108
|
return {
|
|
95
109
|
id: info.id,
|
|
96
|
-
name: info
|
|
110
|
+
name: workBuddyDisplayName(info),
|
|
97
111
|
api: "openai-completions",
|
|
98
112
|
provider: WORKBUDDY_PROVIDER,
|
|
99
113
|
baseUrl,
|
|
@@ -409,6 +423,22 @@ const WORKBUDDY_MODELS_REFRESH_PATH = "/plugins/dsh-connect-workbuddy/models/ref
|
|
|
409
423
|
const WORKBUDDY_ACCOUNTS_REFRESH_PATH = "/plugins/dsh-connect-workbuddy/accounts/refresh";
|
|
410
424
|
/** Plugin-owned daily check-in action endpoint. */
|
|
411
425
|
const WORKBUDDY_CHECKIN_PATH = "/plugins/dsh-connect-workbuddy/checkin";
|
|
426
|
+
/**
|
|
427
|
+
* Project one card row into its persisted `lastCatalog` shape: the native
|
|
428
|
+
* context window becomes the stored `contextWindow`, and the card-only
|
|
429
|
+
* presentation fields (`nativeContextWindow`, `multimodal`) are removed BY
|
|
430
|
+
* KEY. They must never be set to `undefined`: explicit `undefined` values
|
|
431
|
+
* survive `structuredClone` and are rejected by the settings write path's
|
|
432
|
+
* strict JSON codec (`client api: settings/mutate rejected "ops"`), which
|
|
433
|
+
* fails the whole save.
|
|
434
|
+
*/
|
|
435
|
+
function toPersistedWorkBuddyModel(model) {
|
|
436
|
+
const { nativeContextWindow, multimodal: _cardOnly, ...rest } = model;
|
|
437
|
+
return {
|
|
438
|
+
...rest,
|
|
439
|
+
contextWindow: nativeContextWindow
|
|
440
|
+
};
|
|
441
|
+
}
|
|
412
442
|
//#endregion
|
|
413
443
|
//#region src/web-status.ts
|
|
414
444
|
/** Redact token-like content before it crosses to the browser. */
|
|
@@ -731,7 +761,7 @@ function apply(ctx, config) {
|
|
|
731
761
|
if (request.provider !== "workbuddy") return [];
|
|
732
762
|
return withImageSelection(deriveCatalog(await discoverModels(signal), enabledSet(current()), current().contextBudgets ?? {}), imageSet(current())).map((model) => ({
|
|
733
763
|
id: model.id,
|
|
734
|
-
name: model
|
|
764
|
+
name: workBuddyDisplayName(model),
|
|
735
765
|
contextWindow: model.contextWindow,
|
|
736
766
|
maxTokens: model.maxTokens,
|
|
737
767
|
inputModalities: workBuddyModelInput(model)
|
|
@@ -760,4 +790,4 @@ function apply(ctx, config) {
|
|
|
760
790
|
});
|
|
761
791
|
}
|
|
762
792
|
//#endregion
|
|
763
|
-
export { Config, FALLBACK_WORKBUDDY_MODELS, WORKBUDDY_ACCOUNTS_REFRESH_PATH, WORKBUDDY_AUTH_FILENAME, WORKBUDDY_AUTH_FILE_ENV, WORKBUDDY_CHECKIN_PATH, WORKBUDDY_CONNECT_VERSION, WORKBUDDY_HOST_HEARTBEAT_FILENAME, WORKBUDDY_MODELS_REFRESH_PATH, WORKBUDDY_PROVIDER, WORKBUDDY_SETTINGS_NS, WORKBUDDY_STREAM_IDLE_TIMEOUT_MS, WORKBUDDY_USAGE_PATH, WorkBuddyCatalog, WorkBuddyCredentialStore, WorkBuddyUpstreamClient, apply, authFileName, classifyUpstreamError, clearHostHeartbeat, createWorkBuddyAdapter, createWorkBuddyShim, defaultDesktopAuthCandidates, defaultDesktopAuthDirs, defaultDesktopAuthPath, deriveCatalog, inject, isHeartbeatProcessAlive, name, parseCreditMultiplier, parseReasoning, parseUpstreamModel, parseWorkBuddyAuth, prepareChatBody, processStartTimeMs, readHostHeartbeat, regionOf, registerWorkBuddyStatusRoute, workBuddyModelInput, workBuddyThinkingLevelMap, workBuddyWebStatus, workbuddyAccountId, workbuddyHostHeartbeatPath, workbuddyOwnAuthPath, writeHostHeartbeat };
|
|
793
|
+
export { Config, FALLBACK_WORKBUDDY_MODELS, WORKBUDDY_ACCOUNTS_REFRESH_PATH, WORKBUDDY_AUTH_FILENAME, WORKBUDDY_AUTH_FILE_ENV, WORKBUDDY_CHECKIN_PATH, WORKBUDDY_CONNECT_VERSION, WORKBUDDY_HOST_HEARTBEAT_FILENAME, WORKBUDDY_MODELS_REFRESH_PATH, WORKBUDDY_PROVIDER, WORKBUDDY_SETTINGS_NS, WORKBUDDY_STREAM_IDLE_TIMEOUT_MS, WORKBUDDY_USAGE_PATH, WorkBuddyCatalog, WorkBuddyCredentialStore, WorkBuddyUpstreamClient, apply, authFileName, classifyUpstreamError, clearHostHeartbeat, createWorkBuddyAdapter, createWorkBuddyShim, defaultDesktopAuthCandidates, defaultDesktopAuthDirs, defaultDesktopAuthPath, deriveCatalog, inject, isHeartbeatProcessAlive, name, parseCreditMultiplier, parseReasoning, parseUpstreamModel, parseWorkBuddyAuth, prepareChatBody, processStartTimeMs, readHostHeartbeat, regionOf, registerWorkBuddyStatusRoute, toPersistedWorkBuddyModel, workBuddyDisplayName, workBuddyModelInput, workBuddyThinkingLevelMap, workBuddyWebStatus, workbuddyAccountId, workbuddyHostHeartbeatPath, workbuddyOwnAuthPath, writeHostHeartbeat };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-connect-workbuddy",
|
|
3
3
|
"displayName": "DSH Connect WorkBuddy",
|
|
4
4
|
"description": "Connect locally signed-in WorkBuddy models to DeepSeek Harness with a read-only credits overview and model management.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.2.0",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|