dsh-connect-workbuddy 5.12.3 → 5.12.4
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 +90 -4
- package/lib/bin.js +1 -1
- package/lib/{host-heartbeat-D1N-f8Q6.js → host-heartbeat-guET27pw.js} +53 -16
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,91 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.12.4 (2026-10-28)
|
|
4
|
+
|
|
5
|
+
> issue #159 的**报告现象成立,归因不成立**。现场确实出现了「三级救援一级都没跑」的 `11128`,但把它
|
|
6
|
+
> 唯一地归到 `!controller.signal.aborted` 上不成立:**这个 shim 里 `signal` 只有 `res.on('close')`
|
|
7
|
+
> 一个来源**(`src/shim.ts:1657`,客户端真的断开了),不存在 issue 假设的那个「宿主内部中止」的第二来源;
|
|
8
|
+
> 而按建议删掉三处 `&&` 经实测会把**诊断改坏**(见下)。顺着这条线索查同一个阶梯,找到的**真实缺陷是另一个**:
|
|
9
|
+
> 密集救援 rung 在真实大小的 body 上是 **O(n²)**,现场那种 130 KB 提示词要跑**分钟级同步 CPU**,
|
|
10
|
+
> 于是「救援等于没跑」有了一个不依赖 abort 的解释,且这个解释是实测出来的。
|
|
11
|
+
|
|
12
|
+
### Fixes
|
|
13
|
+
|
|
14
|
+
- **密集扰动 rung 的 O(n²):92 KB 的 body 要 82.7 秒,130 KB 的现场提示词要两分多钟(#159 衍生)**
|
|
15
|
+
- **根因**:`perturbChannelFingerprints(body, true)` 用 `replace(/(?=\S)/gu, cb)`,回调里为**每一个**
|
|
16
|
+
匹配位置重新取「上一个非空白字符」,写法是 `source.slice(0, offset).match(/\S(?=\S*$)/u)` ——
|
|
17
|
+
对每个位置做一次 O(offset) 的前缀切片 + 正则,整体 O(n²)。
|
|
18
|
+
- **实测(本机 Node 25,2026-10-28,改动前)**:
|
|
19
|
+
|
|
20
|
+
| body | 耗时 |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| 11,575 字符 | 1.3 s |
|
|
23
|
+
| 23,075 字符 | 5.2 s |
|
|
24
|
+
| 46,075 字符 | 22.8 s |
|
|
25
|
+
| 92,075 字符 | **82.7 s** |
|
|
26
|
+
| 184,075 字符 | 322.8 s |
|
|
27
|
+
|
|
28
|
+
- **为什么这条比「救援没跑」更该先修**:这一级只在网关已经拒过两次之后才走,也就是**恰好**落在大 body
|
|
29
|
+
的真实会话上;而 92 KB 就是一次普通的长会话,#159 现场那条 `system` 是 130,345 字符。这一级是**同步**
|
|
30
|
+
CPU,先跑完才发请求,而 `chatStream` 对自己**刻意不设超时**(它自己的注释解释了原因:真实答案要预填
|
|
31
|
+
整个提示词,卡一个够用的上限必然切掉慢而正常的答案)。于是救援会先被读者自己的等待熬过去,而**从外面看,
|
|
32
|
+
「跑得太慢」和「根本没跑」是同一件事** —— 这正是 #159 观察到的那个现象。
|
|
33
|
+
- **修法**:把这条规则改成**一次累加扫描**(`spaceDenseBreaks`)。规则本身一字未改,输出**逐字节相同**:
|
|
34
|
+
旧写法那句 `/\S(?=\S*$)/u` 要求「其后全部非空白」,所以它取回的其实是**当前这段非空白串的首字符**,
|
|
35
|
+
而不是上一个字符 —— 这个反直觉的细节正是重写时最容易写错的地方(本轮就写错过两次,靠下面的等价测试
|
|
36
|
+
发现)。**这不是「顺手优化」**:改动只碰耗时,字节不动,因为换一个字节就是换一份没人测过的 body。
|
|
37
|
+
- **实测(同一台机器,改动后)**:92 KB 由 **82.7 s → 10 ms**(约 8000 倍);130 KB 的等价 body 在
|
|
38
|
+
**10 ms 量级**完成。
|
|
39
|
+
- **两条新测试各钉住一半**:`tests/issue159-dense-rescue-cost.spec.ts` 用**旧规则的逐字转录**做参照,
|
|
40
|
+
22 个定点用例 + 1500 例定种子随机语料比对**字节相等**;并钉住耗时 —— 130 KB 在 2 s 内完成,
|
|
41
|
+
320 KB 的中位数在 5 s 内完成(真正线性的实现在该尺寸约 15 ms,旧规则约 15 分钟,两者相差三个数量级,
|
|
42
|
+
所以这个上限既不误报也绝不放过)。
|
|
43
|
+
- **耗时断言的度量方式本身改过两次,两次都是被 CI / 变异测试纠正的**:第一版钉 60 KB→120 KB 的
|
|
44
|
+
**比值 < 8**,变异测试显示旧规则在该尺寸的比值恰好 **4.0** —— 8 倍把二次方实现**放过去了**,等于没钉;
|
|
45
|
+
收紧到 **< 3** 后,**CI 又在正确实现上把它跑红**(ubuntu 实测 60 KB 10 ms、120 KB 34 ms,比值 3.4)——
|
|
46
|
+
在个位数毫秒的样本上,比值量到的是计时粒度、GC 和固定开销,不是被主张的增长。最终改为**在能区分两种
|
|
47
|
+
实现的尺寸上钉绝对上限**(320 KB / 5 s,中位数),依据是 40→640 KB 的实测每翻倍约 2 倍
|
|
48
|
+
(3.5 / 7.3 / 11.2 / 28.8 / 69.3 ms)。
|
|
49
|
+
|
|
50
|
+
- **未采纳 issue 建议的那一行补丁,并给出实测理由(`tests/issue159-abort-gate.spec.ts`)**
|
|
51
|
+
- issue 的建议是删掉三处 `&& !controller.signal.aborted`,理由是「中止已由下传的 `signal` 在
|
|
52
|
+
`chatStream` 内部保证,外层这道 `&&` 是重复且有害的检查」。**「重复」只对了一半**:删掉之后
|
|
53
|
+
`chatStream` 确实会立刻因 abort 返回,但它返回的是 `{status: 0, kind: 'server'}`(被 abort 的
|
|
54
|
+
`fetch` 抛 `AbortError`,在客户端被兜成传输失败)—— 这个结果会**盖掉**真正的 `channel_reject`
|
|
55
|
+
诊断,读者收到的从「网关拒了这条请求」变成「上游服务器错误」;`reportFailures` 还会为一个**根本没
|
|
56
|
+
上线的请求**记一笔账号失败。
|
|
57
|
+
- **实测对照**(真挂断,客户端按真实 `chatStream` 对 abort 的处理返回):
|
|
58
|
+
|
|
59
|
+
| | 保留门(HEAD) | 删掉门(issue 建议) |
|
|
60
|
+
| --- | --- | --- |
|
|
61
|
+
| 断线后额外调用上游 | **0 次** | 2 次 |
|
|
62
|
+
| 最终 kind | `channel_reject`(真实原因) | `server`(自己造出来的) |
|
|
63
|
+
| 账号测量 | **不记** | 记一笔假的 |
|
|
64
|
+
|
|
65
|
+
- 保留的正是 #159 真正关心的那一半:**请求还活着时的 11128,三级照跑**。这一半由
|
|
66
|
+
`issue113-channel-gate-evidence.spec.ts` / `issue98-shim.spec.ts` 覆盖,本轮又加了一条同文件内的
|
|
67
|
+
对照用例,防止将来有人以「救援没跑」为名再把门删掉。
|
|
68
|
+
- 变异验证:把三处 `&&` 删掉 → 新增的断线用例**变红**(`the shim spent a rescue on an aborted signal:
|
|
69
|
+
expected 1 to be +0`),对照用例**仍绿**。
|
|
70
|
+
|
|
71
|
+
### 未改动(据实说明)
|
|
72
|
+
|
|
73
|
+
- issue 里「`retries` 为空」这个字段名**在本仓库不存在**:实际实现是失败文案里的「,并已用…重试过」
|
|
74
|
+
(`src/shim.ts:2067-2071`),`Error` 信封里没有 `retries` 字段。报告者读到的可能是宿主侧的包装,
|
|
75
|
+
本仓库无法据该字段反推,故不据此改动任何判定。
|
|
76
|
+
- issue 的另一半(5.12.3 的 `IDENTITY_CLAUSE` + `neutralizeScannedText` 已修好)与本次改动无关,未触碰。
|
|
77
|
+
|
|
78
|
+
### 验证
|
|
79
|
+
|
|
80
|
+
- 端到端对照:同一个 **116,939 字符**的现场形状 body(三段身份句 + 无标点长 prose + 20 轮 assistant
|
|
81
|
+
历史)走完整 shim,三级阶梯全部跑完后答 200 —— **修复后 29 ms,修复前 144,260 ms(2 分 24 秒)**。
|
|
82
|
+
这一条是本次的真正判据:旧代码不是「永远救不回来」,而是慢到读者早已放弃。
|
|
83
|
+
- 变异验证(每条都确认会让对应用例变红):删掉三处 `&& !controller.signal.aborted` → 新增断线用例
|
|
84
|
+
**变红**(`the shim spent a rescue on an aborted signal: expected 1 to be +0`);把密集规则退回 O(n²)
|
|
85
|
+
实现 → **160 KB 实测 204,670 ms**,超过 5 s 上限 40 倍,**变红**;而正确实现在同一尺寸约 15 ms
|
|
86
|
+
(320 KB 在变异版上跑满 10 分钟未完成,已终止,未作为判据)。
|
|
87
|
+
- 全量:`tsc` 双配置 0 错误,**148 文件 / 2563 通过(2 条按平台跳过)**,`tsdown` 构建通过。
|
|
88
|
+
|
|
3
89
|
## 5.12.3 (2026-10-28)
|
|
4
90
|
|
|
5
91
|
> issue #155 的**两个独立 Bug**:**① 业务码按字节匹配 JSON**——`11128`/`14003`/`14018` 用
|
|
@@ -31,10 +117,10 @@
|
|
|
31
117
|
整个消失**,`channel_reject` 贴出来却没有 `11128` 可锚。第 4 行方向相反(substring 恰好命中嵌套的
|
|
32
118
|
`"code":11128`,解析器当时只认 `error.data.code`),说明这不是「换成解析器就完了」—— 两侧都得读同一个
|
|
33
119
|
事实,才可能一致。
|
|
34
|
-
-
|
|
35
|
-
`result.kind === 'channel_reject'
|
|
36
|
-
|
|
37
|
-
|
|
120
|
+
- **代价不只是文案**:渠道救援阶梯**只认 `channel_reject`**(`src/shim.ts` 的门是
|
|
121
|
+
`result.kind === 'channel_reject'`),所以漏判成任何别的类别都等于整条阶梯不跑 —— `forceNeutralHead` 与两级
|
|
122
|
+
扰动一次都不会触发,用户被要求「调整请求后重试」,而插件根本没试过救援。`14003` 同族实测降级目标**随 HTTP
|
|
123
|
+
状态而变**:`429 {"code": 14003}` → `soft_rate`、`400` → `client`,而 `model_busy` 是三个**不换号**的类别之一
|
|
38
124
|
(`isFailoverWorthy`)—— 落到 `soft_rate` 就是让整个账号池挨个烧一次真实请求去学一个模型级的事实。
|
|
39
125
|
`14018` spaced 单独看会掉成 `client`,实测只有当 `msg` 里带上了 `Credits exhausted` 那句话时才被
|
|
40
126
|
措辞标记救回 `hard_credit` —— 措辞一改就失效,正是本仓库反复记录的那类脆弱判据。
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as WorkBuddyCredentialStore, D as defaultDesktopAuthDirs, E as defaultDesktopAuthCandidates, I as workbuddyOwnAuthPath, Lt as WORKBUDDY_APP_EXECUTABLE_ENV, M as legacyWorkbuddyOwnAuthPath, S as WORKBUDDY_AUTH_FILE_ENV, Ut as findWorkbuddyAppExecutableWithSource, V as WorkBuddyUpstreamClient, Zt as hostPeersInfo, a as readHostHeartbeat, c as WORKBUDDY_CONNECT_VERSION, d as rosterSeenPath, f as piAiRuntimeInfo, m as FALLBACK_WORKBUDDY_MODELS_GLOBAL, o as workbuddyHostHeartbeatPath, p as FALLBACK_WORKBUDDY_MODELS, r as isHeartbeatProcessAlive, u as describeRosterSeenPayload } from "./host-heartbeat-
|
|
2
|
+
import { C as WorkBuddyCredentialStore, D as defaultDesktopAuthDirs, E as defaultDesktopAuthCandidates, I as workbuddyOwnAuthPath, Lt as WORKBUDDY_APP_EXECUTABLE_ENV, M as legacyWorkbuddyOwnAuthPath, S as WORKBUDDY_AUTH_FILE_ENV, Ut as findWorkbuddyAppExecutableWithSource, V as WorkBuddyUpstreamClient, Zt as hostPeersInfo, a as readHostHeartbeat, c as WORKBUDDY_CONNECT_VERSION, d as rosterSeenPath, f as piAiRuntimeInfo, m as FALLBACK_WORKBUDDY_MODELS_GLOBAL, o as workbuddyHostHeartbeatPath, p as FALLBACK_WORKBUDDY_MODELS, r as isHeartbeatProcessAlive, u as describeRosterSeenPayload } from "./host-heartbeat-guET27pw.js";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { realpathSync } from "node:fs";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -2536,12 +2536,12 @@ function asBusinessCode(value) {
|
|
|
2536
2536
|
* runs the OTHER way (the substring happens to hit the nested `"code":11128`
|
|
2537
2537
|
* while the parser only knew `error.data.code`), which is why this could not be
|
|
2538
2538
|
* fixed by "just use the parser" — both readers must consult ONE fact.
|
|
2539
|
-
* That is not cosmetic —
|
|
2540
|
-
*
|
|
2541
|
-
*
|
|
2542
|
-
* rungs never
|
|
2543
|
-
*
|
|
2544
|
-
*
|
|
2539
|
+
* That is not cosmetic — the channel rescue ladder runs ONLY for
|
|
2540
|
+
* `channel_reject` (`src/shim.ts` gates on `result.kind === 'channel_reject'`),
|
|
2541
|
+
* so any other kind skips it entirely: `forceNeutralHead` and both perturbation
|
|
2542
|
+
* rungs never fire, and the user is told to "adjust the request" for a refusal
|
|
2543
|
+
* the plugin never tried to rescue. Issue #113's whole fix depends on whether
|
|
2544
|
+
* the upstream happened to emit a space.
|
|
2545
2545
|
*
|
|
2546
2546
|
* THREE READS, IN THIS ORDER, and the ordering is the safety property:
|
|
2547
2547
|
*
|
|
@@ -2867,10 +2867,12 @@ function isChannelGateFamilyBody(body) {
|
|
|
2867
2867
|
* ADVISES, and that is {@link channelGateMemberOf}'s job, decided by the
|
|
2868
2868
|
* plugin's own evidence rather than by a wording the upstream may misreport.
|
|
2869
2869
|
*
|
|
2870
|
-
* The code is
|
|
2871
|
-
*
|
|
2872
|
-
*
|
|
2873
|
-
*
|
|
2870
|
+
* The code is read by {@link statesBusinessCode}, exactly as the family test
|
|
2871
|
+
* above it does — this function adds nothing to that decision and must not
|
|
2872
|
+
* appear to own a rule of its own. The reason the code is READ rather than
|
|
2873
|
+
* text-matched is unchanged (issue #155): a request id is hexadecimal and can
|
|
2874
|
+
* contain the digits `11128` by coincidence, and a bare substring search over an
|
|
2875
|
+
* arbitrary failure body is how a red herring gets promoted into a diagnosis.
|
|
2874
2876
|
*/
|
|
2875
2877
|
function isChannelRejectBody(body) {
|
|
2876
2878
|
return isChannelGateFamilyBody(body);
|
|
@@ -3686,6 +3688,45 @@ const ZERO_WIDTH_SPACE = "";
|
|
|
3686
3688
|
* rather than rewriting the text.
|
|
3687
3689
|
*/
|
|
3688
3690
|
const WORD_INTERNAL_BREAK = /([A-Z][A-Za-z0-9]*)(\s+)(?=[A-Z][A-Za-z0-9])/gu;
|
|
3691
|
+
/** A rune the dense rescue treats as a word character. */
|
|
3692
|
+
const DENSE_WORD_RUNE = /[A-Za-z0-9-ヿ㐀-鿿]/u;
|
|
3693
|
+
/**
|
|
3694
|
+
* Space U+200B through each run of non-space runes, when that run starts with a
|
|
3695
|
+
* word rune.
|
|
3696
|
+
*
|
|
3697
|
+
* THE ONE-PASS FORM OF THE DENSE RULE (issue #159). The rule only ever consults
|
|
3698
|
+
* two local facts — the first rune of the CURRENT run of non-space runes, and
|
|
3699
|
+
* whether the rune immediately before this position is already a break — so it
|
|
3700
|
+
* needs one accumulator and no prefix slicing, which is what makes it linear
|
|
3701
|
+
* rather than quadratic. See the body for why the reference is the run's FIRST
|
|
3702
|
+
* rune rather than the previous one, and for the exact old expression it
|
|
3703
|
+
* reproduces.
|
|
3704
|
+
*
|
|
3705
|
+
* It is kept as a standalone function so its output can be compared against a
|
|
3706
|
+
* literal transcription of the old `replace` in the test suite: the rewrite is
|
|
3707
|
+
* a performance change only, and a byte-difference would mean the rescue sends
|
|
3708
|
+
* a body nobody measured.
|
|
3709
|
+
*/
|
|
3710
|
+
function spaceDenseBreaks(text) {
|
|
3711
|
+
const runes = Array.from(text);
|
|
3712
|
+
let out = "";
|
|
3713
|
+
/** First rune of the current run of non-space runes; `undefined` outside one. */
|
|
3714
|
+
let runStart;
|
|
3715
|
+
for (let index = 0; index < runes.length; index += 1) {
|
|
3716
|
+
const rune = runes[index];
|
|
3717
|
+
if (/^\s$/u.test(rune)) {
|
|
3718
|
+
runStart = void 0;
|
|
3719
|
+
out += rune;
|
|
3720
|
+
continue;
|
|
3721
|
+
}
|
|
3722
|
+
runStart ??= rune;
|
|
3723
|
+
const inRun = index > 0 && !/^\s$/u.test(runes[index - 1]);
|
|
3724
|
+
const before = runes[index - 1];
|
|
3725
|
+
if (inRun && runStart !== ZERO_WIDTH_SPACE && DENSE_WORD_RUNE.test(runStart) && rune !== ZERO_WIDTH_SPACE && before !== ZERO_WIDTH_SPACE) out += ZERO_WIDTH_SPACE;
|
|
3726
|
+
out += rune;
|
|
3727
|
+
}
|
|
3728
|
+
return out;
|
|
3729
|
+
}
|
|
3689
3730
|
/**
|
|
3690
3731
|
* A body whose scanned message TEXT is perturbed just enough to break an exact
|
|
3691
3732
|
* content fingerprint.
|
|
@@ -3748,11 +3789,7 @@ function perturbChannelFingerprints(bodyJson, dense = false) {
|
|
|
3748
3789
|
const perturb = (text) => {
|
|
3749
3790
|
const boundaries = text.replace(/([.!?])(\s+)/gu, `$1${ZERO_WIDTH_SPACE}$2`).replace(/([。!?])(?!\u200b)/gu, `$1${ZERO_WIDTH_SPACE}`).replace(/([,;])(\s+)/gu, `$1${ZERO_WIDTH_SPACE}$2`).replace(WORD_INTERNAL_BREAK, (whole, head, tail) => `${head}${ZERO_WIDTH_SPACE}${tail}`);
|
|
3750
3791
|
if (!dense) return boundaries === text ? void 0 : boundaries;
|
|
3751
|
-
const denseText = boundaries
|
|
3752
|
-
if (source.slice(Math.max(0, offset - 1), offset + 1).includes(ZERO_WIDTH_SPACE)) return "";
|
|
3753
|
-
const previous = source.slice(0, offset).match(/\S(?=\S*$)/u)?.[0];
|
|
3754
|
-
return previous !== void 0 && /[A-Za-z0-9-ヿ㐀-鿿]/u.test(previous) ? ZERO_WIDTH_SPACE : "";
|
|
3755
|
-
});
|
|
3792
|
+
const denseText = spaceDenseBreaks(boundaries);
|
|
3756
3793
|
return denseText === text ? void 0 : denseText;
|
|
3757
3794
|
};
|
|
3758
3795
|
for (const value of messages) {
|
|
@@ -7674,7 +7711,7 @@ function describeRosterSeenPayload(raw) {
|
|
|
7674
7711
|
//#endregion
|
|
7675
7712
|
//#region src/version.ts
|
|
7676
7713
|
/** The npm package version this build was produced from. */
|
|
7677
|
-
const WORKBUDDY_CONNECT_VERSION = "5.12.
|
|
7714
|
+
const WORKBUDDY_CONNECT_VERSION = "5.12.4";
|
|
7678
7715
|
//#endregion
|
|
7679
7716
|
//#region src/host-heartbeat.ts
|
|
7680
7717
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as parseCreditMultiplier, $t as withFileLock, A as isEncryptedCredentialError, At as pickMediaModel, B as WorkBuddyCredentialRejectedError, Bt as deriveAtRestKeyId, C as WorkBuddyCredentialStore, Ct as IMAGE_TAG_TEXT_TO_IMAGE, D as defaultDesktopAuthDirs, Dt as imageMimeForPath, E as defaultDesktopAuthCandidates, Et as imageDataUrl, F as workbuddyAccountId, Ft as imageDefaultFor, G as forceNeutralHead, Gt as isWorkbuddyBundle, H as channelGateMemberOf, Ht as findWorkbuddyAppExecutable, I as workbuddyOwnAuthPath, It as nativeModalityOf, J as isCredentialRejectedError, Jt as openEncryptedField, K as isContextTooLongBody, Kt as macosBundleExecutable, L as CONTEXT_OVERFLOW_MARKER, Lt as WORKBUDDY_APP_EXECUTABLE_ENV, M as legacyWorkbuddyOwnAuthPath, Mt as parseQueueAnswer, N as parseWorkBuddyAuth, Nt as queueNoticeText, O as defaultDesktopAuthPath, Ot as isBareBase64Image, P as preferredAccountName, Pt as NATIVE_MODALITY_BY_MODEL_ID, Q as openingEvidenceOfBody, Qt as resolveDshHome, R as CREDENTIAL_REJECTED_CODE, Rt as clearAtRestKeyCache, S as WORKBUDDY_AUTH_FILE_ENV, St as IMAGE_TAG_IMAGE_TO_IMAGE, T as authFileName, Tt as WorkBuddyImageError, U as classifyUpstreamError, V as WorkBuddyUpstreamClient, Vt as fetchAtRestKeyPayload, W as declaredTools, Wt as isEncryptedFieldWrapper, X as knownRegionOf, Xt as workbuddyAppExecutableCandidates, Y as isFirstMessageGateBody, Yt as readAtRestKey, Z as modelIdOfBody, _ as deriveCatalog, _t as WorkBuddyVideoError, a as readHostHeartbeat, at as requestEvidenceOf, b as ENCRYPTED_CREDENTIAL_CODE, bt as resolveVideoParams, c as WORKBUDDY_CONNECT_VERSION, ct as REFUSES_OFF_MODEL_IDS, dt as offDefaultFor, en as writeFileAtomic, et as parseReasoning, f as piAiRuntimeInfo, ft as offRefused, g as applyContextBudgets, gt as VIDEO_TAG_TEXT_TO_VIDEO, h as WorkBuddyCatalog, ht as VIDEO_TAG_IMAGE_TO_VIDEO, i as processStartTimeMs, it as regionOf, j as isVaultAccountId, jt as sniffImageMime, k as hasEncryptedCredentialFields, kt as parseImageDataUrl, l as createFileRosterSeenStore, lt as defaultOffModelIds, m as FALLBACK_WORKBUDDY_MODELS_GLOBAL, mt as withEffectiveOff, n as clearHostHeartbeat, nt as perturbChannelFingerprints, o as workbuddyHostHeartbeatPath, ot as rewriteSessionTitleModel, p as FALLBACK_WORKBUDDY_MODELS, pt as recordRefusal, q as isConversationIdGateBody, qt as macosNestedAppBundles, r as isHeartbeatProcessAlive, rt as prepareChatBody, s as writeHostHeartbeat, st as attachBusyLevels, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, tt as parseUpstreamModel, ut as lastRefusalFor, v as fallbackModelsFor, vt as parseSupportedSecondsRange, w as WorkBuddyEncryptedCredentialError, wt as MAX_INPUT_IMAGE_BYTES, x as WORKBUDDY_AUTH_FILENAME, xt as DEFAULT_IMAGE_SIZE, y as withoutRouters, yt as pickVideoModel, z as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, zt as deriveAtRestKey } from "./host-heartbeat-
|
|
1
|
+
import { $ as parseCreditMultiplier, $t as withFileLock, A as isEncryptedCredentialError, At as pickMediaModel, B as WorkBuddyCredentialRejectedError, Bt as deriveAtRestKeyId, C as WorkBuddyCredentialStore, Ct as IMAGE_TAG_TEXT_TO_IMAGE, D as defaultDesktopAuthDirs, Dt as imageMimeForPath, E as defaultDesktopAuthCandidates, Et as imageDataUrl, F as workbuddyAccountId, Ft as imageDefaultFor, G as forceNeutralHead, Gt as isWorkbuddyBundle, H as channelGateMemberOf, Ht as findWorkbuddyAppExecutable, I as workbuddyOwnAuthPath, It as nativeModalityOf, J as isCredentialRejectedError, Jt as openEncryptedField, K as isContextTooLongBody, Kt as macosBundleExecutable, L as CONTEXT_OVERFLOW_MARKER, Lt as WORKBUDDY_APP_EXECUTABLE_ENV, M as legacyWorkbuddyOwnAuthPath, Mt as parseQueueAnswer, N as parseWorkBuddyAuth, Nt as queueNoticeText, O as defaultDesktopAuthPath, Ot as isBareBase64Image, P as preferredAccountName, Pt as NATIVE_MODALITY_BY_MODEL_ID, Q as openingEvidenceOfBody, Qt as resolveDshHome, R as CREDENTIAL_REJECTED_CODE, Rt as clearAtRestKeyCache, S as WORKBUDDY_AUTH_FILE_ENV, St as IMAGE_TAG_IMAGE_TO_IMAGE, T as authFileName, Tt as WorkBuddyImageError, U as classifyUpstreamError, V as WorkBuddyUpstreamClient, Vt as fetchAtRestKeyPayload, W as declaredTools, Wt as isEncryptedFieldWrapper, X as knownRegionOf, Xt as workbuddyAppExecutableCandidates, Y as isFirstMessageGateBody, Yt as readAtRestKey, Z as modelIdOfBody, _ as deriveCatalog, _t as WorkBuddyVideoError, a as readHostHeartbeat, at as requestEvidenceOf, b as ENCRYPTED_CREDENTIAL_CODE, bt as resolveVideoParams, c as WORKBUDDY_CONNECT_VERSION, ct as REFUSES_OFF_MODEL_IDS, dt as offDefaultFor, en as writeFileAtomic, et as parseReasoning, f as piAiRuntimeInfo, ft as offRefused, g as applyContextBudgets, gt as VIDEO_TAG_TEXT_TO_VIDEO, h as WorkBuddyCatalog, ht as VIDEO_TAG_IMAGE_TO_VIDEO, i as processStartTimeMs, it as regionOf, j as isVaultAccountId, jt as sniffImageMime, k as hasEncryptedCredentialFields, kt as parseImageDataUrl, l as createFileRosterSeenStore, lt as defaultOffModelIds, m as FALLBACK_WORKBUDDY_MODELS_GLOBAL, mt as withEffectiveOff, n as clearHostHeartbeat, nt as perturbChannelFingerprints, o as workbuddyHostHeartbeatPath, ot as rewriteSessionTitleModel, p as FALLBACK_WORKBUDDY_MODELS, pt as recordRefusal, q as isConversationIdGateBody, qt as macosNestedAppBundles, r as isHeartbeatProcessAlive, rt as prepareChatBody, s as writeHostHeartbeat, st as attachBusyLevels, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, tt as parseUpstreamModel, ut as lastRefusalFor, v as fallbackModelsFor, vt as parseSupportedSecondsRange, w as WorkBuddyEncryptedCredentialError, wt as MAX_INPUT_IMAGE_BYTES, x as WORKBUDDY_AUTH_FILENAME, xt as DEFAULT_IMAGE_SIZE, y as withoutRouters, yt as pickVideoModel, z as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, zt as deriveAtRestKey } from "./host-heartbeat-guET27pw.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { appendFile, mkdir, open, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import { randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
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": "5.12.
|
|
5
|
+
"version": "5.12.4",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|