dsh-connect-workbuddy 2.0.14 → 2.0.15
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 +29 -0
- package/lib/bin.js +1 -1
- package/lib/client.js +25 -12
- package/lib/{host-heartbeat-SQNmYRNj.js → host-heartbeat-bvp_AX4w.js} +1 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.15 (2026-09-24)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- **不能正确取消(或启用)国际版 / 国内版区域开关**(用户实报:「我发现现在不能正确取消国际或者国内版本」)。**写入其实一直是成功的**——用户机器上的 `settings.yaml` 已经写着 `regions.global.enabled: false`——失败的是**开关控件没能反映这个事实**,所以看起来像「点了没用」。
|
|
8
|
+
|
|
9
|
+
- **根因(两处,都在读取侧)**:
|
|
10
|
+
|
|
11
|
+
1. **开关读的是浏览器镜像,而写入落在 Host。** 2.0.14 把设置写入改为 **Host 端点优先**(那是唯一不会删掉兄弟区域的写入方),而**端点写入不会更新浏览器的 settings 镜像**——这一滞后在本仓库别处早已注明。开关的勾选态却是从镜像读的:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
checked={regionEnabledOf(settingsScope?.getSnapshot().value, region)}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
于是 Host 已经提交了 `enabled: false`,复选框**仍显示为开**。这同时解释了为什么此前「读法」与「写入顺序」两轮修复都没有暴露它:**写入一直是对的,错的是回显**。
|
|
18
|
+
|
|
19
|
+
2. **切换后不重新读取 Host。** `toggleRegion()` 写完就结束,从不重新拉取状态,因此新值根本没有机会进入卡片。
|
|
20
|
+
|
|
21
|
+
- **修法**:
|
|
22
|
+
- 开关改为**以 Host 的值为准**——Host 在状态载荷里已经送回它按自身 config 判定的 `enabled`(`deps.regionEnabled`)。镜像降级为**兜底**:老版本 Host 没这个字段、或状态尚未加载时,仍按存储文档渲染,而不是靠猜。两边用的是**同一条 opt-out 规则**(只有显式 `false` 才算关闭),因此两个来源不可能互相矛盾——只可能其中一个**过期**。
|
|
23
|
+
- `toggleRegion()` 在写入后 **`await refreshUsage(item)`**,重新读取 Host;失败时**显式报错**,而不是让开关静静地不动。
|
|
24
|
+
- 面板打开时**两个区域都拉取**,而不是只拉当前标签页。两个开关**始终**渲染在标签栏上,只拉当前区域会让另一个开关一直停在镜像兜底上——正是本次要摆脱的那个过期来源。
|
|
25
|
+
|
|
26
|
+
- **回归测试**(`tests/volatile-scope.spec.ts`,9 → 13 例):断言 Host 已提交关闭而镜像仍说开时开关显示为**关**(反向同理)、Host 未应答时回落到镜像、以及兜底路径仍能容忍 `{get(): T}` 活引用(否则会退回「永远显示开」的老毛病)。**变异验证**:把读取改回「只看镜像」→ **2 例立即变红**。
|
|
27
|
+
|
|
28
|
+
### Tests
|
|
29
|
+
|
|
30
|
+
- 341 → 345(新增 4 例:区域开关以 Host 真值为准、镜像仅兜底)。
|
|
31
|
+
|
|
3
32
|
## 2.0.14 (2026-09-23)
|
|
4
33
|
|
|
5
34
|
### Bug Fixes
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { O as workbuddyOwnAuthPath, T as legacyWorkbuddyOwnAuthPath, W as findWorkbuddyAppExecutable, _ as WorkBuddyCredentialStore, a as readHostHeartbeat, b as defaultDesktopAuthCandidates, c as WORKBUDDY_CONNECT_VERSION, g as WORKBUDDY_AUTH_FILE_ENV, j as WorkBuddyUpstreamClient, l as FALLBACK_WORKBUDDY_MODELS, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS_GLOBAL, x as defaultDesktopAuthDirs, z as WORKBUDDY_APP_EXECUTABLE_ENV } from "./host-heartbeat-
|
|
2
|
+
import { O as workbuddyOwnAuthPath, T as legacyWorkbuddyOwnAuthPath, W as findWorkbuddyAppExecutable, _ as WorkBuddyCredentialStore, a as readHostHeartbeat, b as defaultDesktopAuthCandidates, c as WORKBUDDY_CONNECT_VERSION, g as WORKBUDDY_AUTH_FILE_ENV, j as WorkBuddyUpstreamClient, l as FALLBACK_WORKBUDDY_MODELS, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS_GLOBAL, x as defaultDesktopAuthDirs, z as WORKBUDDY_APP_EXECUTABLE_ENV } from "./host-heartbeat-bvp_AX4w.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
|
@@ -865,7 +865,7 @@ window.__ModuleLoader__.load({
|
|
|
865
865
|
(0, react.useEffect)(() => {
|
|
866
866
|
if (!open) return;
|
|
867
867
|
const controller = new AbortController();
|
|
868
|
-
refreshUsage(
|
|
868
|
+
for (const region of WORKBUDDY_REGIONS) refreshUsage(region, controller.signal);
|
|
869
869
|
return () => {
|
|
870
870
|
controller.abort();
|
|
871
871
|
};
|
|
@@ -937,19 +937,29 @@ window.__ModuleLoader__.load({
|
|
|
937
937
|
}
|
|
938
938
|
};
|
|
939
939
|
/**
|
|
940
|
-
* Whether one region's provider is switched on
|
|
941
|
-
* settings document the Host reads (`regionEnabledOf` mirrors the Host's
|
|
942
|
-
* `regionStateOf` opt-out rule: only an explicit `false` disables). Reading
|
|
943
|
-
* the stored value rather than echoing local state means a rejected write,
|
|
944
|
-
* another window's change, or a restart all converge on the truth.
|
|
940
|
+
* Whether one region's provider is switched on.
|
|
945
941
|
*
|
|
946
|
-
* The
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
950
|
-
*
|
|
942
|
+
* The HOST's answer wins, because on this deployment it is the only writer
|
|
943
|
+
* that lands: the switch goes through the plugin's Host save endpoint (that
|
|
944
|
+
* endpoint is the only writer that cannot drop the sibling region), and a
|
|
945
|
+
* write made there does NOT update the browser settings mirror. Reading the
|
|
946
|
+
* mirror therefore left the checkbox stuck ON after a successful disable —
|
|
947
|
+
* "不能正确取消国际版/国内版" — even though `enabled: false` was already in
|
|
948
|
+
* settings.yaml. The Host sends the committed value it derives from its own
|
|
949
|
+
* config (`status.enabled`, see `deps.regionEnabled`), so the card renders
|
|
950
|
+
* that.
|
|
951
|
+
*
|
|
952
|
+
* The mirror stays as the FALLBACK: a host that predates the field, or a
|
|
953
|
+
* status that has not loaded yet, still renders from the stored document
|
|
954
|
+
* rather than guessing. Both rules are the same opt-out rule (only an
|
|
955
|
+
* explicit `false` disables), so the two sources cannot disagree — only one
|
|
956
|
+
* of them can be stale.
|
|
951
957
|
*/
|
|
952
|
-
const regionOn = (item) =>
|
|
958
|
+
const regionOn = (item) => {
|
|
959
|
+
const fromHost = statusByRegion[item]?.enabled;
|
|
960
|
+
if (typeof fromHost === "boolean") return fromHost;
|
|
961
|
+
return regionEnabledOf(settingsScope?.getSnapshot().value, item);
|
|
962
|
+
};
|
|
953
963
|
const activeRegionOn = regionOn(activeRegion);
|
|
954
964
|
/**
|
|
955
965
|
* Switch one region's provider off or on. The write carries the region's
|
|
@@ -970,6 +980,9 @@ window.__ModuleLoader__.load({
|
|
|
970
980
|
try {
|
|
971
981
|
const slot = nextRegionEnabled(settingsScope.getSnapshot().value, item, enabled)[item];
|
|
972
982
|
await writeRegionEnabled(settingsScope, item, enabled, typeof slot === "object" && slot !== null ? slot : {});
|
|
983
|
+
await refreshUsage(item);
|
|
984
|
+
} catch (error) {
|
|
985
|
+
if (mounted.current) setAccountError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
973
986
|
} finally {
|
|
974
987
|
if (mounted.current) setTogglingRegion(void 0);
|
|
975
988
|
}
|
|
@@ -2208,7 +2208,7 @@ var WorkBuddyCatalog = class {
|
|
|
2208
2208
|
//#endregion
|
|
2209
2209
|
//#region src/version.ts
|
|
2210
2210
|
/** The npm package version this build was produced from. */
|
|
2211
|
-
const WORKBUDDY_CONNECT_VERSION = "2.0.
|
|
2211
|
+
const WORKBUDDY_CONNECT_VERSION = "2.0.15";
|
|
2212
2212
|
//#endregion
|
|
2213
2213
|
//#region src/host-heartbeat.ts
|
|
2214
2214
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as WorkBuddyCredentialRejectedError, B as clearAtRestKeyCache, C as hasEncryptedCredentialFields, D as workbuddyAccountId, E as parseWorkBuddyAuth, F as parseReasoning, G as isEncryptedFieldWrapper, H as deriveAtRestKeyId, I as parseUpstreamModel, J as macosNestedAppBundles, K as isWorkbuddyBundle, L as prepareChatBody, M as classifyUpstreamError, N as isCredentialRejectedError, O as workbuddyOwnAuthPath, P as parseCreditMultiplier, R as regionOf, S as defaultDesktopAuthPath, T as legacyWorkbuddyOwnAuthPath, U as fetchAtRestKeyPayload, V as deriveAtRestKey, W as findWorkbuddyAppExecutable, X as readAtRestKey, Y as openEncryptedField, Z as workbuddyAppExecutableCandidates, _ as WorkBuddyCredentialStore, a as readHostHeartbeat, b as defaultDesktopAuthCandidates, c as WORKBUDDY_CONNECT_VERSION, d as WorkBuddyCatalog, f as deriveCatalog, g as WORKBUDDY_AUTH_FILE_ENV, h as WORKBUDDY_AUTH_FILENAME, i as processStartTimeMs, j as WorkBuddyUpstreamClient, k as CREDENTIAL_REJECTED_CODE, l as FALLBACK_WORKBUDDY_MODELS, m as ENCRYPTED_CREDENTIAL_CODE, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as fallbackModelsFor, q as macosBundleExecutable, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS_GLOBAL, v as WorkBuddyEncryptedCredentialError, w as isEncryptedCredentialError, x as defaultDesktopAuthDirs, y as authFileName, z as WORKBUDDY_APP_EXECUTABLE_ENV } from "./host-heartbeat-
|
|
1
|
+
import { A as WorkBuddyCredentialRejectedError, B as clearAtRestKeyCache, C as hasEncryptedCredentialFields, D as workbuddyAccountId, E as parseWorkBuddyAuth, F as parseReasoning, G as isEncryptedFieldWrapper, H as deriveAtRestKeyId, I as parseUpstreamModel, J as macosNestedAppBundles, K as isWorkbuddyBundle, L as prepareChatBody, M as classifyUpstreamError, N as isCredentialRejectedError, O as workbuddyOwnAuthPath, P as parseCreditMultiplier, R as regionOf, S as defaultDesktopAuthPath, T as legacyWorkbuddyOwnAuthPath, U as fetchAtRestKeyPayload, V as deriveAtRestKey, W as findWorkbuddyAppExecutable, X as readAtRestKey, Y as openEncryptedField, Z as workbuddyAppExecutableCandidates, _ as WorkBuddyCredentialStore, a as readHostHeartbeat, b as defaultDesktopAuthCandidates, c as WORKBUDDY_CONNECT_VERSION, d as WorkBuddyCatalog, f as deriveCatalog, g as WORKBUDDY_AUTH_FILE_ENV, h as WORKBUDDY_AUTH_FILENAME, i as processStartTimeMs, j as WorkBuddyUpstreamClient, k as CREDENTIAL_REJECTED_CODE, l as FALLBACK_WORKBUDDY_MODELS, m as ENCRYPTED_CREDENTIAL_CODE, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as fallbackModelsFor, q as macosBundleExecutable, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS_GLOBAL, v as WorkBuddyEncryptedCredentialError, w as isEncryptedCredentialError, x as defaultDesktopAuthDirs, y as authFileName, z as WORKBUDDY_APP_EXECUTABLE_ENV } from "./host-heartbeat-bvp_AX4w.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";
|
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": "2.0.
|
|
5
|
+
"version": "2.0.15",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|