dsh-connect-workbuddy 5.6.0 → 5.6.1

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
+ ## 5.6.1 (2026-10-23)
4
+
5
+ > 补丁版本:修 5.6.0 自己引入的一处显示回退。**请求路径、provider 路由、计费与凭据一律未变。**
6
+
7
+ ### Fixes
8
+
9
+ - **模型选择器里积分倍率显示了两遍(#120 回归)**
10
+ - **症状**:5.6.0 之后选择器每一行都是 `DeepSeek-V4.1-Flash · x0.11 · x0.11`。截图在 5.6.0 发布后几分钟内报告。
11
+ - **根因**:宿主的模型名**本来就以倍率结尾**(`workBuddyDisplayName` 拼的是 `"<name> · x<multiplier>"`,宿主原样渲染),#120 又在这个字符串旁边追加了一个倍率 span,于是同一个数字出现两次。**不是 #120 的判定错了,是我加渲染时没注意那串名字里已经有一个。**
12
+ - **修法**:新增 `splitCatalogRate()`,把倍率**从宿主字符串里剥出来**、再画到能承载折后值的那个 span 里——始终只有一个数字,且它是此刻生效的那个。后缀按**形状**识别(`· x<数字>` 结尾),不按快照的 `baseRate` 比:目录价可能在快照与渲染之间变化,靠值比对会留下旧后缀、又变成两个数字,正是这个函数要消掉的东西。
13
+ - **测试**:新增 `tests/issue120-picker-rate-duplicate.spec.tsx`(8 条)——剥离后缀保留原值、折扣时**替换**而非追加、快照过期仍按形状剥离、无倍率的名字不动、无后缀时用快照值、无后缀时仍能显示折扣、名字中间的 `x` 不动、`x0.00`(免费)不被当成「没有倍率」。
14
+
3
15
  ## 5.6.0 (2026-10-23)
4
16
 
5
17
  > 特性版本:两条都来自 issue 报告——#120(错峰时段的积分倍率没跟着变)与 #124(企业/教育版账号积分恒为 0、姓名显示成登录别名)。**请求路径、provider 路由、渠道门与计费口径一律未变**;改的是「倍率与徽标同源同时钟」和「企业账号读自己那张计费表」。
package/lib/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { C as defaultDesktopAuthCandidates, L as WorkBuddyUpstreamClient, M as workbuddyOwnAuthPath, Mt as hostPeersInfo, a as readHostHeartbeat, b as WorkBuddyCredentialStore, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, k as legacyWorkbuddyOwnAuthPath, l as piAiRuntimeInfo, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, vt as WORKBUDDY_APP_EXECUTABLE_ENV, w as defaultDesktopAuthDirs, wt as findWorkbuddyAppExecutableWithSource, y as WORKBUDDY_AUTH_FILE_ENV } from "./host-heartbeat-DqTNlE6H.js";
2
+ import { C as defaultDesktopAuthCandidates, L as WorkBuddyUpstreamClient, M as workbuddyOwnAuthPath, Mt as hostPeersInfo, a as readHostHeartbeat, b as WorkBuddyCredentialStore, c as WORKBUDDY_CONNECT_VERSION, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, k as legacyWorkbuddyOwnAuthPath, l as piAiRuntimeInfo, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, vt as WORKBUDDY_APP_EXECUTABLE_ENV, w as defaultDesktopAuthDirs, wt as findWorkbuddyAppExecutableWithSource, y as WORKBUDDY_AUTH_FILE_ENV } from "./host-heartbeat-CEYnXXF3.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
@@ -8840,12 +8840,12 @@ window.__ModuleLoader__.load({
8840
8840
  (0, react.useEffect)(() => subscribeMinute(() => setTick((count) => count + 1)), []);
8841
8841
  const level = snapshot?.levels[modelId];
8842
8842
  const promo = snapshot === void 0 ? void 0 : selectPromoBadge(snapshot.promos[modelId], Date.now());
8843
- const baseRate = snapshot?.rates[modelId];
8844
- const rate = (snapshot === void 0 ? void 0 : selectPromoMultiplier(snapshot.promos[modelId], Date.now())) ?? baseRate;
8843
+ const discounted = snapshot === void 0 ? void 0 : selectPromoMultiplier(snapshot.promos[modelId], Date.now());
8844
+ const { base, rate } = splitCatalogRate(name, snapshot?.rates[modelId], discounted);
8845
8845
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8846
8846
  className: "dsm-workbuddy-model-label",
8847
8847
  children: [
8848
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: name }),
8848
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: base }),
8849
8849
  rate === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
8850
8850
  className: "dsm-workbuddy-model-label-rate",
8851
8851
  children: [" · x", rate.toFixed(2)]
@@ -8858,6 +8858,36 @@ window.__ModuleLoader__.load({
8858
8858
  ]
8859
8859
  });
8860
8860
  }
8861
+ /**
8862
+ * Split the host's display name into "name" and "the multiplier to show".
8863
+ *
8864
+ * `workBuddyDisplayName` builds `"<name> · x<multiplier>"` and the host renders
8865
+ * that string verbatim, so appending another rate next to it printed the figure
8866
+ * twice in the picker (`DeepSeek-V4.1-Flash · x0.11 · x0.11`). The suffix is
8867
+ * therefore pulled back OUT of the string and re-drawn in the span that can
8868
+ * carry the discounted value — exactly one number, and it is the one that holds
8869
+ * right now.
8870
+ *
8871
+ * The suffix is recognised by SHAPE, not by comparing against the snapshot's
8872
+ * `baseRate`: the two can disagree (a promotion can change the catalog figure
8873
+ * between the snapshot and this render), and leaving the suffix in place then
8874
+ * prints two numbers again — the very defect this function removes.
8875
+ *
8876
+ * @param name - The host's rendered name, possibly ending in ` · x<rate>`.
8877
+ * @param baseRate - The catalog multiplier, as the snapshot reports it.
8878
+ * @param discounted - The rate to show instead, when a discount is running.
8879
+ * @returns The name without its rate suffix, and the single rate to draw.
8880
+ * `undefined` means "draw no number" (the name had none and no
8881
+ * discount is running).
8882
+ */
8883
+ function splitCatalogRate(name, baseRate, discounted) {
8884
+ const match = / · x(\d+(?:\.\d+)?)$/.exec(name);
8885
+ const fromName = match === null ? void 0 : Number(match[1]);
8886
+ return {
8887
+ base: match === null ? name : name.slice(0, match.index),
8888
+ rate: discounted ?? fromName ?? baseRate
8889
+ };
8890
+ }
8861
8891
  //#endregion
8862
8892
  //#region src/client/CodebuddyLive.tsx
8863
8893
  /**
@@ -6121,7 +6121,7 @@ function generationOf(version) {
6121
6121
  //#endregion
6122
6122
  //#region src/version.ts
6123
6123
  /** The npm package version this build was produced from. */
6124
- const WORKBUDDY_CONNECT_VERSION = "5.6.0";
6124
+ const WORKBUDDY_CONNECT_VERSION = "5.6.1";
6125
6125
  //#endregion
6126
6126
  //#region src/host-heartbeat.ts
6127
6127
  /**
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as prepareChatBody, A as parseWorkBuddyAuth, At as readAtRestKey, B as declaredTools, C as defaultDesktopAuthCandidates, Ct as findWorkbuddyAppExecutable, D as isEncryptedCredentialError, Dt as macosBundleExecutable, E as hasEncryptedCredentialFields, Et as isWorkbuddyBundle, F as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, Ft as writeFileAtomic, G as isFirstMessageGateBody, H as isContextTooLongBody, I as WorkBuddyCredentialRejectedError, J as openingEvidenceOfBody, K as knownRegionOf, L as WorkBuddyUpstreamClient, M as workbuddyOwnAuthPath, N as CONTEXT_OVERFLOW_MARKER, Nt as resolveDshHome, O as isVaultAccountId, Ot as macosNestedAppBundles, P as CREDENTIAL_REJECTED_CODE, Pt as withFileLock, Q as perturbChannelFingerprints, R as channelGateMemberOf, S as authFileName, St as fetchAtRestKeyPayload, T as defaultDesktopAuthPath, Tt as isEncryptedFieldWrapper, U as isConversationIdGateBody, V as forceNeutralHead, W as isCredentialRejectedError, X as parseReasoning, Y as parseCreditMultiplier, Z as parseUpstreamModel, _ as ENCRYPTED_CREDENTIAL_CODE, _t as nativeModalityOf, a as readHostHeartbeat, at as lastRefusalFor, b as WorkBuddyCredentialStore, bt as deriveAtRestKey, c as WORKBUDDY_CONNECT_VERSION, ct as recordRefusal, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, dt as WorkBuddyImageError, et as regionOf, f as WorkBuddyCatalog, ft as pickImageModel, g as withoutRouters, gt as imageDefaultFor, h as fallbackModelsFor, ht as NATIVE_MODALITY_BY_MODEL_ID, i as processStartTimeMs, it as defaultOffModelIds, j as workbuddyAccountId, jt as workbuddyAppExecutableCandidates, k as legacyWorkbuddyOwnAuthPath, kt as openEncryptedField, l as piAiRuntimeInfo, lt as withEffectiveOff, m as deriveCatalog, mt as queueNoticeText, n as clearHostHeartbeat, nt as attachBusyLevels, o as workbuddyHostHeartbeatPath, ot as offDefaultFor, p as applyContextBudgets, pt as parseQueueAnswer, q as modelIdOfBody, r as isHeartbeatProcessAlive, rt as REFUSES_OFF_MODEL_IDS, s as writeHostHeartbeat, st as offRefused, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, tt as requestEvidenceOf, u as FALLBACK_WORKBUDDY_MODELS, ut as DEFAULT_IMAGE_SIZE, v as WORKBUDDY_AUTH_FILENAME, vt as WORKBUDDY_APP_EXECUTABLE_ENV, w as defaultDesktopAuthDirs, x as WorkBuddyEncryptedCredentialError, xt as deriveAtRestKeyId, y as WORKBUDDY_AUTH_FILE_ENV, yt as clearAtRestKeyCache, z as classifyUpstreamError } from "./host-heartbeat-DqTNlE6H.js";
1
+ import { $ as prepareChatBody, A as parseWorkBuddyAuth, At as readAtRestKey, B as declaredTools, C as defaultDesktopAuthCandidates, Ct as findWorkbuddyAppExecutable, D as isEncryptedCredentialError, Dt as macosBundleExecutable, E as hasEncryptedCredentialFields, Et as isWorkbuddyBundle, F as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, Ft as writeFileAtomic, G as isFirstMessageGateBody, H as isContextTooLongBody, I as WorkBuddyCredentialRejectedError, J as openingEvidenceOfBody, K as knownRegionOf, L as WorkBuddyUpstreamClient, M as workbuddyOwnAuthPath, N as CONTEXT_OVERFLOW_MARKER, Nt as resolveDshHome, O as isVaultAccountId, Ot as macosNestedAppBundles, P as CREDENTIAL_REJECTED_CODE, Pt as withFileLock, Q as perturbChannelFingerprints, R as channelGateMemberOf, S as authFileName, St as fetchAtRestKeyPayload, T as defaultDesktopAuthPath, Tt as isEncryptedFieldWrapper, U as isConversationIdGateBody, V as forceNeutralHead, W as isCredentialRejectedError, X as parseReasoning, Y as parseCreditMultiplier, Z as parseUpstreamModel, _ as ENCRYPTED_CREDENTIAL_CODE, _t as nativeModalityOf, a as readHostHeartbeat, at as lastRefusalFor, b as WorkBuddyCredentialStore, bt as deriveAtRestKey, c as WORKBUDDY_CONNECT_VERSION, ct as recordRefusal, d as FALLBACK_WORKBUDDY_MODELS_GLOBAL, dt as WorkBuddyImageError, et as regionOf, f as WorkBuddyCatalog, ft as pickImageModel, g as withoutRouters, gt as imageDefaultFor, h as fallbackModelsFor, ht as NATIVE_MODALITY_BY_MODEL_ID, i as processStartTimeMs, it as defaultOffModelIds, j as workbuddyAccountId, jt as workbuddyAppExecutableCandidates, k as legacyWorkbuddyOwnAuthPath, kt as openEncryptedField, l as piAiRuntimeInfo, lt as withEffectiveOff, m as deriveCatalog, mt as queueNoticeText, n as clearHostHeartbeat, nt as attachBusyLevels, o as workbuddyHostHeartbeatPath, ot as offDefaultFor, p as applyContextBudgets, pt as parseQueueAnswer, q as modelIdOfBody, r as isHeartbeatProcessAlive, rt as REFUSES_OFF_MODEL_IDS, s as writeHostHeartbeat, st as offRefused, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, tt as requestEvidenceOf, u as FALLBACK_WORKBUDDY_MODELS, ut as DEFAULT_IMAGE_SIZE, v as WORKBUDDY_AUTH_FILENAME, vt as WORKBUDDY_APP_EXECUTABLE_ENV, w as defaultDesktopAuthDirs, x as WorkBuddyEncryptedCredentialError, xt as deriveAtRestKeyId, y as WORKBUDDY_AUTH_FILE_ENV, yt as clearAtRestKeyCache, z as classifyUpstreamError } from "./host-heartbeat-CEYnXXF3.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.6.0",
5
+ "version": "5.6.1",
6
6
  "author": "dingminhua",
7
7
  "copyright": "Copyright (c) 2026 LaoDing",
8
8
  "license": "MIT",