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-6xWs7ak3.js";
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 **system/developer** message carries the phrase `DeepSeek Harness`
927
- * answers `400` / `11128` "Illegal API invocation from an unapproved channel",
928
- * while the same account, headers and body with the phrase rewritten answers
929
- * 200. DSH injects exactly that phrase as the head of its system prompt
930
- * ("You are an AI agent powered by DeepSeek Harness."), so every request the
931
- * harness sends is affected; the official desktop app never sends it.
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
- * Only `system` / `developer` messages are touched: the same measurement shows
951
- * user messages are not inspected, and rewriting user content would corrupt
952
- * data the plugin has no business editing. Idempotent — a second pass finds
953
- * neither the opener nor a bare phrase.
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 !== "system" && role !== "developer") continue;
962
- const content = message["content"];
963
- if (typeof content === "string") {
964
- message["content"] = neutralizeSignatureText(content);
965
- continue;
966
- }
967
- if (!Array.isArray(content)) continue;
968
- for (const part of content) {
969
- if (!isObject(part) || part["type"] !== "text") continue;
970
- const text = part["text"];
971
- if (typeof text === "string") part["text"] = neutralizeSignatureText(text);
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.2";
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-6xWs7ak3.js";
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.2",
5
+ "version": "0.5.3",
6
6
  "author": "zlZayn",
7
7
  "keywords": [
8
8
  "dsh",