dsh-connect-workbuddy 3.4.1 → 3.4.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.4.2 (2026-10-03)
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- **换号重试之间补上 2 秒间隔,不再零延迟连发。**
|
|
8
|
+
- **现象**:一次请求撞上限流后,换号循环会**零间隔**地把池里剩下的账号挨个试一遍——实测 4 个账号在 **35 秒内全部失败**(最后两次只隔 1 秒),而它们全部撞的是同一个 429。
|
|
9
|
+
- **根因**:上游的限流(业务码 6004)**按请求体积/频率触发**,零间隔连发等于自己把每个候选都推到同一堵墙上。批量测试早就为此在账号之间等 `POOL_BATCH_GAP_MS`(400ms),**换号循环却什么都没有**——两者的差别没有理由。
|
|
10
|
+
- **修法**:每次换号前等待 `FAILOVER_ACCOUNT_GAP_MS`(2 秒)。比批测的 400ms 更长,因为换号重试是**用户在等的真实请求**,不是探测——它需要给上游的窗口留出喘息,而不只是避免自己踩到限流。
|
|
11
|
+
- **等待是可中断的**:客户端断开时立刻结束等待并退出循环,不会白等 2 秒,也不会拿一个已经作废的 signal 去把剩余账号试完。
|
|
12
|
+
- 顺带修正:等待结束后重新检查一次中断状态——否则客户端已断开时,剩余账号会被逐个发出去(每个都立即因 signal 作废而失败),白白写下一串假的账号失败测量。
|
|
13
|
+
- 测试:新增一条用例钉住「两次尝试之间确实等待了 ≥1.9 秒」,变异验证(把间隔改成 0)必红。
|
|
14
|
+
|
|
3
15
|
## 3.4.1 (2026-10-02)
|
|
4
16
|
|
|
5
17
|
### Fixes
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { E as legacyWorkbuddyOwnAuthPath, H as WORKBUDDY_APP_EXECUTABLE_ENV, N as WorkBuddyUpstreamClient, S as defaultDesktopAuthDirs, _ as WORKBUDDY_AUTH_FILE_ENV, a as readHostHeartbeat, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, k as workbuddyOwnAuthPath, l as piAiRuntimeInfo, o as workbuddyHostHeartbeatPath, q as findWorkbuddyAppExecutable, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, v as WorkBuddyCredentialStore, x as defaultDesktopAuthCandidates } from "./host-heartbeat-
|
|
2
|
+
import { E as legacyWorkbuddyOwnAuthPath, H as WORKBUDDY_APP_EXECUTABLE_ENV, N as WorkBuddyUpstreamClient, S as defaultDesktopAuthDirs, _ as WORKBUDDY_AUTH_FILE_ENV, a as readHostHeartbeat, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, k as workbuddyOwnAuthPath, l as piAiRuntimeInfo, o as workbuddyHostHeartbeatPath, q as findWorkbuddyAppExecutable, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, v as WorkBuddyCredentialStore, x as defaultDesktopAuthCandidates } from "./host-heartbeat-Sq5JwluI.js";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/bin.ts
|
|
@@ -2552,7 +2552,7 @@ function generationOf(version) {
|
|
|
2552
2552
|
//#endregion
|
|
2553
2553
|
//#region src/version.ts
|
|
2554
2554
|
/** The npm package version this build was produced from. */
|
|
2555
|
-
const WORKBUDDY_CONNECT_VERSION = "3.4.
|
|
2555
|
+
const WORKBUDDY_CONNECT_VERSION = "3.4.2";
|
|
2556
2556
|
//#endregion
|
|
2557
2557
|
//#region src/host-heartbeat.ts
|
|
2558
2558
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as readAtRestKey, A as CREDENTIAL_REJECTED_CODE, B as prepareChatBody, C as defaultDesktopAuthPath, D as parseWorkBuddyAuth, E as legacyWorkbuddyOwnAuthPath, F as declaredTools, G as deriveAtRestKeyId, H as WORKBUDDY_APP_EXECUTABLE_ENV, I as isCredentialRejectedError, J as isEncryptedFieldWrapper, K as fetchAtRestKeyPayload, L as parseCreditMultiplier, M as WorkBuddyCredentialRejectedError, N as WorkBuddyUpstreamClient, O as workbuddyAccountId, P as classifyUpstreamError, Q as openEncryptedField, R as parseReasoning, S as defaultDesktopAuthDirs, T as isEncryptedCredentialError, U as clearAtRestKeyCache, V as regionOf, W as deriveAtRestKey, X as macosBundleExecutable, Y as isWorkbuddyBundle, Z as macosNestedAppBundles, _ as WORKBUDDY_AUTH_FILE_ENV, a as readHostHeartbeat, b as authFileName, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, et as workbuddyAppExecutableCandidates, f as WorkBuddyCatalog, g as WORKBUDDY_AUTH_FILENAME, h as ENCRYPTED_CREDENTIAL_CODE, i as processStartTimeMs, j as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, k as workbuddyOwnAuthPath, l as piAiRuntimeInfo, m as fallbackModelsFor, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as deriveCatalog, q as findWorkbuddyAppExecutable, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as WorkBuddyCredentialStore, w as hasEncryptedCredentialFields, x as defaultDesktopAuthCandidates, y as WorkBuddyEncryptedCredentialError, z as parseUpstreamModel } from "./host-heartbeat-
|
|
1
|
+
import { $ as readAtRestKey, A as CREDENTIAL_REJECTED_CODE, B as prepareChatBody, C as defaultDesktopAuthPath, D as parseWorkBuddyAuth, E as legacyWorkbuddyOwnAuthPath, F as declaredTools, G as deriveAtRestKeyId, H as WORKBUDDY_APP_EXECUTABLE_ENV, I as isCredentialRejectedError, J as isEncryptedFieldWrapper, K as fetchAtRestKeyPayload, L as parseCreditMultiplier, M as WorkBuddyCredentialRejectedError, N as WorkBuddyUpstreamClient, O as workbuddyAccountId, P as classifyUpstreamError, Q as openEncryptedField, R as parseReasoning, S as defaultDesktopAuthDirs, T as isEncryptedCredentialError, U as clearAtRestKeyCache, V as regionOf, W as deriveAtRestKey, X as macosBundleExecutable, Y as isWorkbuddyBundle, Z as macosNestedAppBundles, _ as WORKBUDDY_AUTH_FILE_ENV, a as readHostHeartbeat, b as authFileName, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, et as workbuddyAppExecutableCandidates, f as WorkBuddyCatalog, g as WORKBUDDY_AUTH_FILENAME, h as ENCRYPTED_CREDENTIAL_CODE, i as processStartTimeMs, j as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, k as workbuddyOwnAuthPath, l as piAiRuntimeInfo, m as fallbackModelsFor, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as deriveCatalog, q as findWorkbuddyAppExecutable, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as WorkBuddyCredentialStore, w as hasEncryptedCredentialFields, x as defaultDesktopAuthCandidates, y as WorkBuddyEncryptedCredentialError, z as parseUpstreamModel } from "./host-heartbeat-Sq5JwluI.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
@@ -1118,6 +1118,19 @@ function finish(parts, calls) {
|
|
|
1118
1118
|
* @module dsh-connect-workbuddy/shim
|
|
1119
1119
|
*/
|
|
1120
1120
|
const REQUEST_BODY_LIMIT = 67108864;
|
|
1121
|
+
/**
|
|
1122
|
+
* Pause between failover attempts, after one account's request failed.
|
|
1123
|
+
*
|
|
1124
|
+
* The upstream's rate limit (6004) fires on request volume — firing retries at
|
|
1125
|
+
* zero gap makes every candidate hit the same wall, and 4 accounts can all fail
|
|
1126
|
+
* in under a second. The batch test already waits `POOL_BATCH_GAP_MS` (400ms)
|
|
1127
|
+
* between accounts for exactly this reason; the failover loop used to wait
|
|
1128
|
+
* nothing. 2 seconds is longer than the batch's 400 because a failover retry is
|
|
1129
|
+
* a real request the user is waiting on, not a probe — it needs enough room for
|
|
1130
|
+
* the upstream's window to breathe, not just enough to avoid self-inflicted
|
|
1131
|
+
* rate-limiting.
|
|
1132
|
+
*/
|
|
1133
|
+
const FAILOVER_ACCOUNT_GAP_MS = 2e3;
|
|
1121
1134
|
/** Loopback hostnames the shim's own in-process client uses. */
|
|
1122
1135
|
const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
|
|
1123
1136
|
"127.0.0.1",
|
|
@@ -1745,6 +1758,16 @@ function createWorkBuddyShim(options) {
|
|
|
1745
1758
|
const next = await failoverAccount(triedAccountIds).catch(() => void 0);
|
|
1746
1759
|
if (next === void 0) break;
|
|
1747
1760
|
if (triedAccountIds.includes(workbuddyAccountId(next))) break;
|
|
1761
|
+
if (controller.signal.aborted) break;
|
|
1762
|
+
await new Promise((resolve) => {
|
|
1763
|
+
if (controller.signal.aborted) return resolve();
|
|
1764
|
+
const timer = setTimeout(resolve, FAILOVER_ACCOUNT_GAP_MS);
|
|
1765
|
+
controller.signal.addEventListener("abort", () => {
|
|
1766
|
+
clearTimeout(timer);
|
|
1767
|
+
resolve();
|
|
1768
|
+
}, { once: true });
|
|
1769
|
+
});
|
|
1770
|
+
if (controller.signal.aborted) break;
|
|
1748
1771
|
logger?.warn(`dsh-connect-workbuddy: retrying chat on another pool account after ${result.kind} (http ${result.status})`);
|
|
1749
1772
|
credential = next;
|
|
1750
1773
|
result = await client.chatStream(credential, prepared, controller.signal);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-connect-workbuddy",
|
|
3
3
|
"displayName": "DSH Connect WorkBuddy",
|
|
4
4
|
"description": "把本机登录的 WorkBuddy 模型接入 DeepSeek Harness,并提供只读的积分概览与模型管理。",
|
|
5
|
-
"version": "3.4.
|
|
5
|
+
"version": "3.4.2",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|