dsh-workbuddy-bridge 0.5.2 → 0.5.3
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/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as variantFor, D as WorkBuddyUpstreamClient, S as WORKBUDDY_VARIANTS, X as resolveAppVersion, a as readHostHeartbeat, c as WORKBUDDY_BRIDGE_VERSION, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, x as CN_VARIANT } from "./heartbeat-
|
|
2
|
+
import { C as variantFor, D as WorkBuddyUpstreamClient, S as WORKBUDDY_VARIANTS, X as resolveAppVersion, a as readHostHeartbeat, c as WORKBUDDY_BRIDGE_VERSION, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, x as CN_VARIANT } from "./heartbeat-BJrYAacX.js";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/cli/bin.ts
|
|
@@ -923,12 +923,12 @@ function prepareChatBody(source) {
|
|
|
923
923
|
* client signature.
|
|
924
924
|
*
|
|
925
925
|
* Measured 2026-10-21 on `copilot.tencent.com/v2/chat/completions`: a request
|
|
926
|
-
* whose
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
*
|
|
926
|
+
* whose message bodies carry the phrase `DeepSeek Harness` answers `400` /
|
|
927
|
+
* `11128` "Illegal API invocation from an unapproved channel", while the same
|
|
928
|
+
* account, headers and body with the phrase rewritten answers 200. DSH injects
|
|
929
|
+
* exactly that phrase as the head of its system prompt ("You are an AI agent
|
|
930
|
+
* powered by DeepSeek Harness."), so every request the harness sends is
|
|
931
|
+
* affected; the official desktop app never sends it.
|
|
932
932
|
*
|
|
933
933
|
* Two rewrites, in this order, because they solve different halves of it:
|
|
934
934
|
*
|
|
@@ -947,10 +947,26 @@ function prepareChatBody(source) {
|
|
|
947
947
|
* into a silently wrong path. Both rewrites anchor on the surrounding slashes
|
|
948
948
|
* for that reason.
|
|
949
949
|
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
952
|
-
*
|
|
953
|
-
*
|
|
950
|
+
* **Roles covered** — `system`, `developer` and `assistant`; `user` and `tool`
|
|
951
|
+
* are left alone. Measured 2026-10-21 by ablation against the same gateway
|
|
952
|
+
* (independently reproduced on the CPA-plugin side and published as
|
|
953
|
+
* mmqz/cpa-multi-plugins PR #49 — a sibling fix, not this repo's upstream and
|
|
954
|
+
* not a dependency): the filter reads `system` and `assistant` bodies, and in
|
|
955
|
+
* that request the triggering phrases sat mostly in the **assistant history
|
|
956
|
+
* echo** — a 32 KB compaction summary carried 42 brand occurrences, and
|
|
957
|
+
* rewriting only `system` still answered 400. The same ablation found `user`
|
|
958
|
+
* text, tool results, tool definitions, `tool_calls` arguments and
|
|
959
|
+
* `reasoning_content` did not fire.
|
|
960
|
+
*
|
|
961
|
+
* This stays narrower than "every role" on purpose. The two excluded kinds are
|
|
962
|
+
* the ones whose bytes are ground truth for the model: user input is the user's
|
|
963
|
+
* own words, and a tool result is what a file or command actually returned.
|
|
964
|
+
* Rewriting either would make the transcript disagree with the world the model
|
|
965
|
+
* is reasoning about — a silent correctness bug traded for a filter that, per
|
|
966
|
+
* the measurement, is not looking there. If the filter later widens, that is a
|
|
967
|
+
* decision with fresh evidence, not something to pre-empt.
|
|
968
|
+
*
|
|
969
|
+
* Idempotent — a second pass finds neither the opener nor a bare phrase.
|
|
954
970
|
*/
|
|
955
971
|
function neutralizeChannelSignature(obj) {
|
|
956
972
|
const messages = obj["messages"];
|
|
@@ -958,18 +974,47 @@ function neutralizeChannelSignature(obj) {
|
|
|
958
974
|
for (const message of messages) {
|
|
959
975
|
if (!isObject(message)) continue;
|
|
960
976
|
const role = message["role"];
|
|
961
|
-
if (role
|
|
962
|
-
|
|
963
|
-
if (
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
977
|
+
if (role === "user" || role === "tool") continue;
|
|
978
|
+
neutralizeMessageText(message);
|
|
979
|
+
if (role === "assistant") neutralizeAssistantExtras(message);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
/** Rewrite a message's string `content`, or each text part of an array `content`. */
|
|
983
|
+
function neutralizeMessageText(message) {
|
|
984
|
+
const content = message["content"];
|
|
985
|
+
if (typeof content === "string") {
|
|
986
|
+
message["content"] = neutralizeSignatureText(content);
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
if (!Array.isArray(content)) return;
|
|
990
|
+
for (const part of content) {
|
|
991
|
+
if (!isObject(part) || part["type"] !== "text") continue;
|
|
992
|
+
const text = part["text"];
|
|
993
|
+
if (typeof text === "string") part["text"] = neutralizeSignatureText(text);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Rewrite the assistant-only carriers that can reach the wire.
|
|
998
|
+
*
|
|
999
|
+
* `reasoning_content` / `reasoning` are the model's own thinking echoed back on
|
|
1000
|
+
* a replayed assistant turn, and `tool_calls[].function.arguments` is a JSON
|
|
1001
|
+
* string the model wrote earlier. Both are model-generated, so rewriting them
|
|
1002
|
+
* keeps the transcript self-consistent, and the path guard still protects any
|
|
1003
|
+
* real directory name quoted inside a tool argument.
|
|
1004
|
+
*/
|
|
1005
|
+
function neutralizeAssistantExtras(message) {
|
|
1006
|
+
for (const key of ["reasoning_content", "reasoning"]) {
|
|
1007
|
+
const value = message[key];
|
|
1008
|
+
if (typeof value === "string") message[key] = neutralizeSignatureText(value);
|
|
1009
|
+
}
|
|
1010
|
+
const toolCalls = message["tool_calls"];
|
|
1011
|
+
if (!Array.isArray(toolCalls)) return;
|
|
1012
|
+
for (const call of toolCalls) {
|
|
1013
|
+
if (!isObject(call)) continue;
|
|
1014
|
+
const fn = call["function"];
|
|
1015
|
+
if (!isObject(fn)) continue;
|
|
1016
|
+
const args = fn["arguments"];
|
|
1017
|
+
if (typeof args === "string") fn["arguments"] = neutralizeSignatureText(args);
|
|
973
1018
|
}
|
|
974
1019
|
}
|
|
975
1020
|
/** Apply the two signature rewrites to one string; see {@link neutralizeChannelSignature}. */
|
|
@@ -3872,7 +3917,7 @@ var WorkBuddyCatalog = class {
|
|
|
3872
3917
|
};
|
|
3873
3918
|
//#endregion
|
|
3874
3919
|
//#region src/version.ts
|
|
3875
|
-
const WORKBUDDY_BRIDGE_VERSION = "0.5.
|
|
3920
|
+
const WORKBUDDY_BRIDGE_VERSION = "0.5.3";
|
|
3876
3921
|
//#endregion
|
|
3877
3922
|
//#region src/web/heartbeat.ts
|
|
3878
3923
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as parseModelCatalog, B as FALLBACK_CN_APP_VERSION, C as variantFor, D as WorkBuddyUpstreamClient, F as probeModel, G as validCliVersion, H as fallbackChatIdentity, I as randomSentinel, J as installedAppVersion, K as WORKBUDDY_APP_VERSION_FILENAME, L as classifyUpstreamError, M as prepareInternationalChatBody, N as regionOf, O as modelWithCurrentPromotion, P as PROBE_EFFORT_CANDIDATES, R as upstreamDisplayMessage, S as WORKBUDDY_VARIANTS, U as readCliVersion, V as chatUserAgent, W as resolveChatIdentity, X as resolveAppVersion, Y as readBundleVersion, Z as validAppVersion, _ as desktopAuthCandidatesFor, a as readHostHeartbeat, b as AI_VARIANT, c as WORKBUDDY_BRIDGE_VERSION, d as WorkBuddyCatalog, f as WORKBUDDY_AUTH_FILENAME, g as defaultDesktopAuthPath, h as defaultDesktopAuthCandidates, i as processStartTimeMs, j as prepareChatBody, k as normalizeCredits, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as WORKBUDDY_AUTH_FILE_ENV, q as appUserAgent, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as parseWorkBuddyAuth, w as WORKBUDDY_CREDIT_PATH, x as CN_VARIANT, y as workbuddyOwnAuthPath, z as CN_APP_VERSION_FILENAME } from "./heartbeat-
|
|
1
|
+
import { A as parseModelCatalog, B as FALLBACK_CN_APP_VERSION, C as variantFor, D as WorkBuddyUpstreamClient, F as probeModel, G as validCliVersion, H as fallbackChatIdentity, I as randomSentinel, J as installedAppVersion, K as WORKBUDDY_APP_VERSION_FILENAME, L as classifyUpstreamError, M as prepareInternationalChatBody, N as regionOf, O as modelWithCurrentPromotion, P as PROBE_EFFORT_CANDIDATES, R as upstreamDisplayMessage, S as WORKBUDDY_VARIANTS, U as readCliVersion, V as chatUserAgent, W as resolveChatIdentity, X as resolveAppVersion, Y as readBundleVersion, Z as validAppVersion, _ as desktopAuthCandidatesFor, a as readHostHeartbeat, b as AI_VARIANT, c as WORKBUDDY_BRIDGE_VERSION, d as WorkBuddyCatalog, f as WORKBUDDY_AUTH_FILENAME, g as defaultDesktopAuthPath, h as defaultDesktopAuthCandidates, i as processStartTimeMs, j as prepareChatBody, k as normalizeCredits, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as WORKBUDDY_AUTH_FILE_ENV, q as appUserAgent, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as parseWorkBuddyAuth, w as WORKBUDDY_CREDIT_PATH, x as CN_VARIANT, y as workbuddyOwnAuthPath, z as CN_APP_VERSION_FILENAME } from "./heartbeat-BJrYAacX.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-workbuddy-bridge",
|
|
3
3
|
"displayName": "DSH WorkBuddy Bridge",
|
|
4
4
|
"description": "将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness — bring WorkBuddy desktop app models into DeepSeek Harness with zero configuration.",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.3",
|
|
6
6
|
"author": "zlZayn",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"dsh",
|