dsh-connect-workbuddy 5.7.0 → 5.8.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 +74 -0
- package/README.en.md +4 -1
- package/README.md +4 -1
- package/docs/WINDOWS.md +6 -0
- package/lib/bin.js +58 -3
- package/lib/client.js +800 -142
- package/lib/{host-heartbeat-CVz2J0Xt.js → host-heartbeat-CM-09T4U.js} +685 -30
- package/lib/index.d.ts +278 -4
- package/lib/index.js +89 -12
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as parseCreditMultiplier, A as isEncryptedCredentialError, At as isWorkbuddyBundle, B as WorkBuddyCredentialRejectedError, C as WorkBuddyCredentialStore, Ct as clearAtRestKeyCache, D as defaultDesktopAuthDirs, Dt as findWorkbuddyAppExecutable, E as defaultDesktopAuthCandidates, Et as fetchAtRestKeyPayload, F as workbuddyAccountId, Ft as workbuddyAppExecutableCandidates, G as forceNeutralHead, H as channelGateMemberOf, I as workbuddyOwnAuthPath, J as isCredentialRejectedError, K as isContextTooLongBody, L as CONTEXT_OVERFLOW_MARKER, Lt as resolveDshHome, M as legacyWorkbuddyOwnAuthPath, Mt as macosNestedAppBundles, N as parseWorkBuddyAuth, Nt as openEncryptedField, O as defaultDesktopAuthPath, P as preferredAccountName, Pt as readAtRestKey, Q as openingEvidenceOfBody, R as CREDENTIAL_REJECTED_CODE, Rt as withFileLock, S as WORKBUDDY_AUTH_FILE_ENV, St as WORKBUDDY_APP_EXECUTABLE_ENV, T as authFileName, Tt as deriveAtRestKeyId, U as classifyUpstreamError, V as WorkBuddyUpstreamClient, W as declaredTools, X as knownRegionOf, Y as isFirstMessageGateBody, Z as modelIdOfBody, _ as deriveCatalog, _t as parseQueueAnswer, a as readHostHeartbeat, at as requestEvidenceOf, b as ENCRYPTED_CREDENTIAL_CODE, bt as imageDefaultFor, c as WORKBUDDY_CONNECT_VERSION, ct as defaultOffModelIds, dt as offRefused, et as parseReasoning, f as piAiRuntimeInfo, ft as recordRefusal, g as applyContextBudgets, gt as pickImageModel, h as WorkBuddyCatalog, ht as WorkBuddyImageError, i as processStartTimeMs, it as regionOf, j as isVaultAccountId, jt as macosBundleExecutable, k as hasEncryptedCredentialFields, kt as isEncryptedFieldWrapper, l as createFileRosterSeenStore, lt as lastRefusalFor, m as FALLBACK_WORKBUDDY_MODELS_GLOBAL, mt as DEFAULT_IMAGE_SIZE, n as clearHostHeartbeat, nt as perturbChannelFingerprints, o as workbuddyHostHeartbeatPath, ot as attachBusyLevels, p as FALLBACK_WORKBUDDY_MODELS, pt as withEffectiveOff, q as isConversationIdGateBody, r as isHeartbeatProcessAlive, rt as prepareChatBody, s as writeHostHeartbeat, st as REFUSES_OFF_MODEL_IDS, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, tt as parseUpstreamModel, ut as offDefaultFor, v as fallbackModelsFor, vt as queueNoticeText, w as WorkBuddyEncryptedCredentialError, wt as deriveAtRestKey, x as WORKBUDDY_AUTH_FILENAME, xt as nativeModalityOf, y as withoutRouters, yt as NATIVE_MODALITY_BY_MODEL_ID, z as WORKBUDDY_FALLBACK_SYSTEM_PROMPT, zt as writeFileAtomic } from "./host-heartbeat-CM-09T4U.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";
|
|
@@ -3280,6 +3280,7 @@ const KIND_STATUS = {
|
|
|
3280
3280
|
model_busy: 429,
|
|
3281
3281
|
session_dead: 401,
|
|
3282
3282
|
policy_reject: 403,
|
|
3283
|
+
account_restricted: 403,
|
|
3283
3284
|
channel_reject: 400,
|
|
3284
3285
|
model_queue: 429,
|
|
3285
3286
|
not_found: 502,
|
|
@@ -3955,6 +3956,7 @@ function failoverReasonText(failure) {
|
|
|
3955
3956
|
case "model_busy": return "该模型当前繁忙(不是账号问题)";
|
|
3956
3957
|
case "session_dead": return "登录已失效";
|
|
3957
3958
|
case "policy_reject": return "被服务端策略拒绝";
|
|
3959
|
+
case "account_restricted": return "账号被上游限制使用";
|
|
3958
3960
|
case "channel_reject": return "被网关的渠道校验拦截(不是账号、额度或网络问题)";
|
|
3959
3961
|
case "not_found": return "模型不可用";
|
|
3960
3962
|
case "server": return "上游异常";
|
|
@@ -4219,6 +4221,14 @@ function createWorkBuddyShim(options) {
|
|
|
4219
4221
|
const onRequestBody = options.onRequestBody;
|
|
4220
4222
|
const onUpstreamUsage = options.onUpstreamUsage;
|
|
4221
4223
|
const channelPerturbation = options.channelPerturbation ?? "failure";
|
|
4224
|
+
/**
|
|
4225
|
+
* Whether the harness's injected `user` blocks are moved above the real prompt.
|
|
4226
|
+
*
|
|
4227
|
+
* OFF by default (issue #132): the reorder changes the message ORDER the
|
|
4228
|
+
* upstream counts, so it must be the user's deliberate choice rather than a
|
|
4229
|
+
* silent difference after an upgrade.
|
|
4230
|
+
*/
|
|
4231
|
+
const keepPromptLastEnabled = options.keepPromptLast === true;
|
|
4222
4232
|
const SHARED_SECRET = randomBytes(32).toString("base64url");
|
|
4223
4233
|
/**
|
|
4224
4234
|
* Whether this process's prompts have been PROVEN to need the invisible
|
|
@@ -4372,7 +4382,7 @@ function createWorkBuddyShim(options) {
|
|
|
4372
4382
|
return;
|
|
4373
4383
|
}
|
|
4374
4384
|
const raw = (await readBody(req)).toString("utf8");
|
|
4375
|
-
const prepared = prepareChatBody(raw);
|
|
4385
|
+
const prepared = prepareChatBody(raw, { keepPromptLast: keepPromptLastEnabled });
|
|
4376
4386
|
const requestModelId = modelIdOfBody(prepared);
|
|
4377
4387
|
if (onRequestBody !== void 0) try {
|
|
4378
4388
|
onRequestBody(prepared);
|
|
@@ -4534,13 +4544,22 @@ function createWorkBuddyShim(options) {
|
|
|
4534
4544
|
writeOpenAIError(res, 429, "model_queue", `${queueNoticeText(queue)}(上游 code ${queue.code})${note}`, void 0, NO_RETRY_HEADERS);
|
|
4535
4545
|
return;
|
|
4536
4546
|
}
|
|
4547
|
+
if (result.kind === "account_restricted") {
|
|
4548
|
+
const detail = result.detail;
|
|
4549
|
+
const meta = ["账号被上游限制使用"];
|
|
4550
|
+
if (detail?.upstreamCode !== void 0) meta.push(`code ${detail.upstreamCode}`);
|
|
4551
|
+
if (detail?.requestId !== void 0) meta.push(`requestId ${detail.requestId}`);
|
|
4552
|
+
const message = `${detail?.displayMsg ?? clippedUpstreamText(result.message, 200)}(${meta.join(",")})${note}${why}。该账号已被 WorkBuddy 上游按账号限制,与本次请求内容、网络和额度无关;插件会记录该测量并改用其他可用账号。该限制是上游对该账号的判定:重新登录不改变插件认的这个账号,需要 WorkBuddy 官方渠道解除后,在卡片上手动「测试」该账号才会回池`;
|
|
4553
|
+
writeOpenAIError(res, KIND_STATUS[result.kind], result.kind, message, hostErrorCode(result.kind));
|
|
4554
|
+
return;
|
|
4555
|
+
}
|
|
4537
4556
|
if (result.kind === "policy_reject") {
|
|
4538
4557
|
const detail = result.detail;
|
|
4539
4558
|
const lead = detail?.displayMsg ?? clippedUpstreamText(result.message, 200);
|
|
4540
4559
|
const meta = ["服务端策略拒绝"];
|
|
4541
4560
|
if (detail?.upstreamCode !== void 0) meta.push(`code ${detail.upstreamCode}`);
|
|
4542
4561
|
if (detail?.requestId !== void 0) meta.push(`requestId ${detail.requestId}`);
|
|
4543
|
-
const message = `${lead}(${meta.join(",")})${note}。该请求被 WorkBuddy
|
|
4562
|
+
const message = `${lead}(${meta.join(",")})${note}。该请求被 WorkBuddy 服务端策略拒绝;若上游的说明指向内容,重新登录不会解决,可在 WorkBuddy 桌面端用同一账号验证;若它指向账号本身,则需要走官方渠道处理,插件会在遇到该措辞时另行标明`;
|
|
4544
4563
|
writeOpenAIError(res, KIND_STATUS[result.kind], result.kind, message, hostErrorCode(result.kind));
|
|
4545
4564
|
return;
|
|
4546
4565
|
}
|
|
@@ -7060,7 +7079,9 @@ function cooldownOf(input) {
|
|
|
7060
7079
|
*/
|
|
7061
7080
|
function outcomeOfFailure(status, body) {
|
|
7062
7081
|
if (status === 401 || status === 403) {
|
|
7063
|
-
|
|
7082
|
+
const kind = classifyUpstreamError(status, body);
|
|
7083
|
+
if (kind === "policy_reject") return "policy-rejected";
|
|
7084
|
+
if (kind === "account_restricted") return "account-restricted";
|
|
7064
7085
|
return "credential-rejected";
|
|
7065
7086
|
}
|
|
7066
7087
|
switch (classifyUpstreamError(status, body)) {
|
|
@@ -7068,6 +7089,7 @@ function outcomeOfFailure(status, body) {
|
|
|
7068
7089
|
case "model_busy": return "model-busy";
|
|
7069
7090
|
case "hard_credit": return "out-of-credit";
|
|
7070
7091
|
case "session_dead": return "credential-rejected";
|
|
7092
|
+
case "account_restricted": return "account-restricted";
|
|
7071
7093
|
case "channel_reject": return "channel-rejected";
|
|
7072
7094
|
case "not_found": return "not-found";
|
|
7073
7095
|
default: return status === 0 || status >= 500 ? "unavailable" : "failed";
|
|
@@ -7608,6 +7630,7 @@ function exclusionOf(probe, nowMs) {
|
|
|
7608
7630
|
switch (probe.outcome) {
|
|
7609
7631
|
case "ok": return;
|
|
7610
7632
|
case "credential-rejected": return "credential-rejected";
|
|
7633
|
+
case "account-restricted": return "account-restricted";
|
|
7611
7634
|
case "not-found": return "not-found";
|
|
7612
7635
|
case "unavailable": return retryDue(probe, nowMs) ? void 0 : "unavailable";
|
|
7613
7636
|
case "failed": return retryDue(probe, nowMs) ? void 0 : "failed";
|
|
@@ -8649,7 +8672,8 @@ function toWebAccount(account) {
|
|
|
8649
8672
|
domain: account.domain,
|
|
8650
8673
|
source: account.source,
|
|
8651
8674
|
tokenExpiresAtMs: account.tokenExpiresAtMs,
|
|
8652
|
-
selected: account.selected
|
|
8675
|
+
selected: account.selected,
|
|
8676
|
+
...account.enterprise === true ? { enterprise: true } : {}
|
|
8653
8677
|
};
|
|
8654
8678
|
}
|
|
8655
8679
|
/**
|
|
@@ -8759,6 +8783,9 @@ async function workBuddyWebStatus(deps, region, options = {}) {
|
|
|
8759
8783
|
const creditPosition = deps.creditPosition?.(region) ?? "composer";
|
|
8760
8784
|
const imageToolEnabled = deps.imageToolEnabled?.(region) ?? false;
|
|
8761
8785
|
const cliBridgeEnabled = deps.cliBridgeEnabled?.() === true;
|
|
8786
|
+
const cliBridgeModel = deps.cliBridgeModel?.() ?? "";
|
|
8787
|
+
const cliBridgeEffort = deps.cliBridgeEffort?.() ?? "";
|
|
8788
|
+
const cliBridgeRegionOrder = deps.cliBridgeRegionOrder?.() ?? "";
|
|
8762
8789
|
const busyLevels = deps.busyLevels?.(region) ?? {};
|
|
8763
8790
|
const authStatus = await store.status();
|
|
8764
8791
|
const selectionExplicit = store.hasExplicitSelection();
|
|
@@ -8770,6 +8797,9 @@ async function workBuddyWebStatus(deps, region, options = {}) {
|
|
|
8770
8797
|
showCreditsInMainUi,
|
|
8771
8798
|
imageToolEnabled,
|
|
8772
8799
|
cliBridgeEnabled,
|
|
8800
|
+
cliBridgeModel,
|
|
8801
|
+
cliBridgeEffort,
|
|
8802
|
+
cliBridgeRegionOrder,
|
|
8773
8803
|
busyLevels
|
|
8774
8804
|
};
|
|
8775
8805
|
let credential;
|
|
@@ -8788,6 +8818,9 @@ async function workBuddyWebStatus(deps, region, options = {}) {
|
|
|
8788
8818
|
creditPosition,
|
|
8789
8819
|
imageToolEnabled,
|
|
8790
8820
|
cliBridgeEnabled,
|
|
8821
|
+
cliBridgeModel,
|
|
8822
|
+
cliBridgeEffort,
|
|
8823
|
+
cliBridgeRegionOrder,
|
|
8791
8824
|
busyLevels,
|
|
8792
8825
|
...await store.selectionLost() ? { selectionLost: true } : {},
|
|
8793
8826
|
...webAccounts.length === 0 ? await searchedPaths(store) : {}
|
|
@@ -8796,7 +8829,7 @@ async function workBuddyWebStatus(deps, region, options = {}) {
|
|
|
8796
8829
|
const selected = accounts.find((account) => account.selected);
|
|
8797
8830
|
const account = {
|
|
8798
8831
|
accountId: selected?.id ?? "",
|
|
8799
|
-
accountName: credential
|
|
8832
|
+
accountName: preferredAccountName(credential),
|
|
8800
8833
|
...credential.domain === "" ? {} : { domain: credential.domain },
|
|
8801
8834
|
region,
|
|
8802
8835
|
source: credential.source,
|
|
@@ -8807,6 +8840,9 @@ async function workBuddyWebStatus(deps, region, options = {}) {
|
|
|
8807
8840
|
creditPosition,
|
|
8808
8841
|
imageToolEnabled,
|
|
8809
8842
|
cliBridgeEnabled,
|
|
8843
|
+
cliBridgeModel,
|
|
8844
|
+
cliBridgeEffort,
|
|
8845
|
+
cliBridgeRegionOrder,
|
|
8810
8846
|
busyLevels,
|
|
8811
8847
|
accounts: accounts.map(toWebAccount),
|
|
8812
8848
|
models: deps.displayModels(region).map((model) => toWebModel(model, deps.contextBudgets(region))).map((model) => model.reasoning === void 0 || lastRefusalFor(model.id) === void 0 ? model : {
|
|
@@ -8821,6 +8857,7 @@ async function workBuddyWebStatus(deps, region, options = {}) {
|
|
|
8821
8857
|
offModelIds: [...deps.offModelIds(region)]
|
|
8822
8858
|
};
|
|
8823
8859
|
const figures = fast ? {} : await liveFigures(deps, region, credential, selected);
|
|
8860
|
+
const rosterSeen = deps.rosterSeen === void 0 ? void 0 : await deps.rosterSeen(region);
|
|
8824
8861
|
return {
|
|
8825
8862
|
status: "signed-in",
|
|
8826
8863
|
contextBudgets: Object.fromEntries(Object.entries(deps.contextBudgets(region)).filter(([, value]) => typeof value === "number")),
|
|
@@ -8830,6 +8867,10 @@ async function workBuddyWebStatus(deps, region, options = {}) {
|
|
|
8830
8867
|
authFile: volatileFlagOf("authFile")
|
|
8831
8868
|
},
|
|
8832
8869
|
...account,
|
|
8870
|
+
...rosterSeen === void 0 ? {} : {
|
|
8871
|
+
newModelIds: [...rosterSeen.newModelIds],
|
|
8872
|
+
...rosterSeen.versionNote === void 0 ? {} : { rosterSeenVersionNote: rosterSeen.versionNote }
|
|
8873
|
+
},
|
|
8833
8874
|
...figures,
|
|
8834
8875
|
...await poolSectionOf(deps, region, fast)
|
|
8835
8876
|
};
|
|
@@ -8902,6 +8943,7 @@ async function workBuddyWebPool(deps, region, fast = false) {
|
|
|
8902
8943
|
return {
|
|
8903
8944
|
accountId: account.id,
|
|
8904
8945
|
accountName: account.accountName,
|
|
8946
|
+
...account.enterprise === true ? { enterprise: true } : {},
|
|
8905
8947
|
...measured?.credits === void 0 ? {} : {
|
|
8906
8948
|
credits: measured.credits.total,
|
|
8907
8949
|
expiringSoon: measured.credits.expiringSoon,
|
|
@@ -9084,6 +9126,7 @@ function registerWorkBuddyStatusRoute(ctx, deps) {
|
|
|
9084
9126
|
try {
|
|
9085
9127
|
const credential = await deps.store(region).credentialFor(accountId);
|
|
9086
9128
|
if (credential === void 0) return json(res, 404, { error: "no credential for this account" });
|
|
9129
|
+
if (credential.enterpriseId !== void 0 && credential.enterpriseId !== "") return json(res, 409, { error: "enterprise-account-unsupported" });
|
|
9087
9130
|
const target = (await deps.client.fetchBenefits(credential)).find((benefit) => benefit.kind === kind);
|
|
9088
9131
|
if (target === void 0) return json(res, 404, { error: "benefit not available on this account" });
|
|
9089
9132
|
if (target.claimed) return json(res, 409, {
|
|
@@ -9701,7 +9744,9 @@ const Config = z.object({
|
|
|
9701
9744
|
z.const("off"),
|
|
9702
9745
|
z.const("failure"),
|
|
9703
9746
|
z.const("always")
|
|
9704
|
-
]).default("failure").description("When to perturb scanned messages with invisible characters: \"off\" only rescues after a channel-gate refusal, \"failure\" (default) learns from a successful rescue and starts later requests perturbed, \"always\" starts every request with the dense rescue for a gateway whose plain attempt is guaranteed to fail."))
|
|
9747
|
+
]).default("failure").description("When to perturb scanned messages with invisible characters: \"off\" only rescues after a channel-gate refusal, \"failure\" (default) learns from a successful rescue and starts later requests perturbed, \"always\" starts every request with the dense rescue for a gateway whose plain attempt is guaranteed to fail.")),
|
|
9748
|
+
usageIdentity: asVolatile(z.boolean().default(false).description("Make the upstream's usage page record these calls like the official client's: add the X-IDE-* identity headers (which fill the 使用端 column) and send the conversation ids as 32-hex UUIDv7. Off by default — it is a display alignment measured by a reporter, not by this plugin, and the chat channel identity (User-Agent) and request body never change.")),
|
|
9749
|
+
keepPromptLast: asVolatile(z.boolean().default(false).description("Move the harness-injected runtime context above the real prompt, so the WorkBuddy usage page records what you actually typed instead of the injected block. Message count and text are preserved; the one edit is the recorded prompt's own leading <acp> marker. Off by default because it changes the message order the upstream counts."))
|
|
9705
9750
|
});
|
|
9706
9751
|
/**
|
|
9707
9752
|
* One region's saved model state. A config written before the region split has
|
|
@@ -9804,7 +9849,7 @@ async function legacyAttributionRegion(value, accountsFor) {
|
|
|
9804
9849
|
function apply(ctx, config) {
|
|
9805
9850
|
const client = new WorkBuddyUpstreamClient((message) => {
|
|
9806
9851
|
ctx.logger.warn(`dsh-connect-workbuddy: ${message}`);
|
|
9807
|
-
});
|
|
9852
|
+
}, { usageIdentity: unwrapVolatile(config.usageIdentity) === true });
|
|
9808
9853
|
/**
|
|
9809
9854
|
* How long a check-in reading is reused before asking the upstream again.
|
|
9810
9855
|
*
|
|
@@ -9842,6 +9887,7 @@ function apply(ctx, config) {
|
|
|
9842
9887
|
refresh: (credential) => client.refreshToken(credential)
|
|
9843
9888
|
});
|
|
9844
9889
|
const catalog = new WorkBuddyCatalog(region);
|
|
9890
|
+
const rosterSeen = createFileRosterSeenStore(region);
|
|
9845
9891
|
/**
|
|
9846
9892
|
* Where the next upstream `usage` should be written.
|
|
9847
9893
|
*
|
|
@@ -9862,6 +9908,7 @@ function apply(ctx, config) {
|
|
|
9862
9908
|
catalog,
|
|
9863
9909
|
logger: ctx.logger,
|
|
9864
9910
|
channelPerturbation: unwrapVolatile(config.channelPerturbation) ?? "failure",
|
|
9911
|
+
keepPromptLast: unwrapVolatile(config.keepPromptLast) === true,
|
|
9865
9912
|
/**
|
|
9866
9913
|
* Pool routing, bound to THIS region.
|
|
9867
9914
|
*
|
|
@@ -9894,7 +9941,8 @@ function apply(ctx, config) {
|
|
|
9894
9941
|
onAccountFailure: (accountId, failure) => {
|
|
9895
9942
|
recordAccountFailure(region, accountId, failure);
|
|
9896
9943
|
}
|
|
9897
|
-
})
|
|
9944
|
+
}),
|
|
9945
|
+
rosterSeen
|
|
9898
9946
|
};
|
|
9899
9947
|
}
|
|
9900
9948
|
const accountUsabilityProbe = createAccountUsabilityProbe({
|
|
@@ -10310,6 +10358,15 @@ function apply(ctx, config) {
|
|
|
10310
10358
|
offModelIds: (region) => savedOffModelIds(regionStateOf(current(), region), displayModels(current(), region)),
|
|
10311
10359
|
contextBudgets: (region) => regionStateOf(current(), region).contextBudgets ?? {},
|
|
10312
10360
|
discoverModels,
|
|
10361
|
+
/**
|
|
10362
|
+
* This region's first-sighting readout, the data behind the composer pill's
|
|
10363
|
+
* "· N 新模型" segment.
|
|
10364
|
+
*
|
|
10365
|
+
* READ-ONLY here: only the reconciler's `note` writes first-sighting
|
|
10366
|
+
* history, so no amount of polling by the pill or the card can change who
|
|
10367
|
+
* counts as new — the one property that keeps the marker honest.
|
|
10368
|
+
*/
|
|
10369
|
+
rosterSeen: (region) => stacks[region].rosterSeen.readout(),
|
|
10313
10370
|
regionEnabled: (region) => regionEnabled(current(), region),
|
|
10314
10371
|
/**
|
|
10315
10372
|
* The region's committed sidebar-credit flag, read from the same config the
|
|
@@ -10335,6 +10392,16 @@ function apply(ctx, config) {
|
|
|
10335
10392
|
*/
|
|
10336
10393
|
cliBridgeEnabled: () => unwrapVolatile(current().cliBridge)?.enabled === true,
|
|
10337
10394
|
/**
|
|
10395
|
+
* The model / reasoning effort the optional CodeBuddy CLI route runs on.
|
|
10396
|
+
*
|
|
10397
|
+
* `cliBridge` is volatile, hence the unwrap; absent keys read as `''` —
|
|
10398
|
+
* "the CLI's own default" — because an empty pin is a COMMITTED value the
|
|
10399
|
+
* card's pickers can render, not a missing one.
|
|
10400
|
+
*/
|
|
10401
|
+
cliBridgeModel: () => unwrapVolatile(current().cliBridge)?.model ?? "",
|
|
10402
|
+
cliBridgeEffort: () => unwrapVolatile(current().cliBridge)?.effort ?? "",
|
|
10403
|
+
cliBridgeRegionOrder: () => unwrapVolatile(current().cliBridge)?.regionOrder ?? "",
|
|
10404
|
+
/**
|
|
10338
10405
|
* WHERE the readout sits, resolved here rather than read from the browser
|
|
10339
10406
|
* settings mirror, for the same measured reason as the flag above: on the
|
|
10340
10407
|
* affected 0.1.7 deployments that mirror never picks up this plugin's
|
|
@@ -10498,7 +10565,8 @@ function apply(ctx, config) {
|
|
|
10498
10565
|
const wanted = new Set(poolPreferencesOf(current(), region).memberAccountIds);
|
|
10499
10566
|
return (await stacks[region].store.accounts()).filter((account) => !wanted.has(account.id)).map((account) => ({
|
|
10500
10567
|
id: account.id,
|
|
10501
|
-
accountName: account.accountName
|
|
10568
|
+
accountName: account.accountName,
|
|
10569
|
+
...account.enterprise === true ? { enterprise: true } : {}
|
|
10502
10570
|
}));
|
|
10503
10571
|
},
|
|
10504
10572
|
/**
|
|
@@ -10571,6 +10639,7 @@ function apply(ctx, config) {
|
|
|
10571
10639
|
if (cached !== void 0 && now - cached.atMs < 18e5) return [account.id, cached.views];
|
|
10572
10640
|
const credential = await store.credentialFor(account.id).catch(() => void 0);
|
|
10573
10641
|
if (credential === void 0) return void 0;
|
|
10642
|
+
if (credential.enterpriseId !== void 0 && credential.enterpriseId !== "") return [account.id, []];
|
|
10574
10643
|
const read = await client.fetchBenefits(credential).catch(() => void 0);
|
|
10575
10644
|
if (read === void 0) return void 0;
|
|
10576
10645
|
const views = claimableBenefits(read, now);
|
|
@@ -10882,6 +10951,7 @@ function apply(ctx, config) {
|
|
|
10882
10951
|
case "out-of-credit": return "账号积分耗尽";
|
|
10883
10952
|
case "model-busy": return "账号撞上模型繁忙";
|
|
10884
10953
|
case "credential-rejected": return "账号登录已失效";
|
|
10954
|
+
case "account-restricted": return "账号被上游限制使用";
|
|
10885
10955
|
case "not-found": return "账号已不存在";
|
|
10886
10956
|
case "unusable": return "账号不可用";
|
|
10887
10957
|
default: return "账号不可用";
|
|
@@ -10921,7 +10991,8 @@ function apply(ctx, config) {
|
|
|
10921
10991
|
return {
|
|
10922
10992
|
account: {
|
|
10923
10993
|
id: account.id,
|
|
10924
|
-
accountName: account.accountName
|
|
10994
|
+
accountName: account.accountName,
|
|
10995
|
+
...account.enterprise === true ? { enterprise: true } : {}
|
|
10925
10996
|
},
|
|
10926
10997
|
...reading === void 0 ? {} : { credits: reading },
|
|
10927
10998
|
...probes[account.id] === void 0 ? {} : { probe: probes[account.id] },
|
|
@@ -11061,7 +11132,8 @@ function apply(ctx, config) {
|
|
|
11061
11132
|
return {
|
|
11062
11133
|
account: {
|
|
11063
11134
|
id: account.id,
|
|
11064
|
-
accountName: account.accountName
|
|
11135
|
+
accountName: account.accountName,
|
|
11136
|
+
...account.enterprise === true ? { enterprise: true } : {}
|
|
11065
11137
|
},
|
|
11066
11138
|
...credits === void 0 ? {} : { credits: {
|
|
11067
11139
|
total: credits.total,
|
|
@@ -11279,6 +11351,11 @@ function apply(ctx, config) {
|
|
|
11279
11351
|
const state = regionStateOf(current(), region);
|
|
11280
11352
|
stacks[region].catalog.set(withEffectiveOff(withImageSelection(deriveCatalog(models, new Set(state.enabledModelIds ?? []), state.contextBudgets ?? {}), new Set(state.imageModelIds ?? [])), new Set(savedOffModelIds(state, models))));
|
|
11281
11353
|
adapters[region].invalidate();
|
|
11354
|
+
try {
|
|
11355
|
+
await stacks[region].rosterSeen.note(models.map((model) => model.id));
|
|
11356
|
+
} catch (error) {
|
|
11357
|
+
ctx.logger.warn(`dsh-connect-workbuddy: ${region} first-sighting history not updated`, error);
|
|
11358
|
+
}
|
|
11282
11359
|
await regionsFieldHealed;
|
|
11283
11360
|
await repairRegionCatalog(region, models);
|
|
11284
11361
|
} catch (error) {
|
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.
|
|
5
|
+
"version": "5.8.1",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|