dsh-connect-workbuddy 5.2.2 → 5.3.0
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 +102 -0
- package/README.en.md +82 -0
- package/README.md +82 -0
- package/lib/bin.js +1 -1
- package/lib/client.js +213 -8
- package/lib/{host-heartbeat-r1M_OXJI.js → host-heartbeat-_EvGiAek.js} +1 -1
- package/lib/index.d.ts +70 -22
- package/lib/index.js +1821 -18
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -530,7 +530,7 @@ window.__ModuleLoader__.load({
|
|
|
530
530
|
headers: { "Content-Type": "application/json" },
|
|
531
531
|
body: JSON.stringify({
|
|
532
532
|
field,
|
|
533
|
-
value: { [region]: value }
|
|
533
|
+
value: region === void 0 ? value : { [region]: value }
|
|
534
534
|
})
|
|
535
535
|
});
|
|
536
536
|
} catch (error) {
|
|
@@ -544,6 +544,56 @@ window.__ModuleLoader__.load({
|
|
|
544
544
|
return (await response.json().catch(() => void 0))?.value;
|
|
545
545
|
}
|
|
546
546
|
/**
|
|
547
|
+
* Read the committed CodeBuddy-CLI switch out of a settings snapshot.
|
|
548
|
+
*
|
|
549
|
+
* Only an explicit `true` is ON, matching the schema's `default(false)`: this
|
|
550
|
+
* switch authorizes a child process that edits files and spends CodeBuddy
|
|
551
|
+
* quota, so an absent value must never read as consent.
|
|
552
|
+
*/
|
|
553
|
+
function cliBridgeEnabledOf(configured) {
|
|
554
|
+
const bridge = configured?.cliBridge;
|
|
555
|
+
return typeof bridge === "object" && bridge !== null && bridge.enabled === true;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Write the GLOBAL CodeBuddy-CLI switch, verifying it landed.
|
|
559
|
+
*
|
|
560
|
+
* Deliberately NOT a region field: one route, one budget, one switch. The two
|
|
561
|
+
* writers are the same as everywhere else — the plugin's Host endpoint first
|
|
562
|
+
* (authoritative merge, so the tuned caps beside `enabled` survive), the
|
|
563
|
+
* settings scope second — because this namespace's browser mirror is documented
|
|
564
|
+
* as stale on the affected 0.1.7 deployments, and a switch that merely *looks*
|
|
565
|
+
* flipped is exactly the "关闭不了" class of report.
|
|
566
|
+
*
|
|
567
|
+
* @param scope - the bound settings scope for this plugin's namespace.
|
|
568
|
+
* @param enabled - the desired state.
|
|
569
|
+
* @throws {WorkBuddySettingsWriteError} when neither writer persists the value.
|
|
570
|
+
*/
|
|
571
|
+
async function writeCliBridgeEnabled(scope, enabled) {
|
|
572
|
+
let hostError;
|
|
573
|
+
try {
|
|
574
|
+
const authoritative = await saveViaHostEndpoint("cliBridge", void 0, { enabled });
|
|
575
|
+
if (authoritative !== void 0) try {
|
|
576
|
+
await scope.set("cliBridge", authoritative);
|
|
577
|
+
} catch {}
|
|
578
|
+
return;
|
|
579
|
+
} catch (error) {
|
|
580
|
+
hostError = error;
|
|
581
|
+
}
|
|
582
|
+
const stored = unwrapVolatileDeep(scope.getSnapshot().value?.cliBridge);
|
|
583
|
+
const next = {
|
|
584
|
+
...typeof stored === "object" && stored !== null ? stored : {},
|
|
585
|
+
enabled
|
|
586
|
+
};
|
|
587
|
+
let delivered = false;
|
|
588
|
+
try {
|
|
589
|
+
delivered = await scope.set("cliBridge", next) !== false;
|
|
590
|
+
} catch {
|
|
591
|
+
delivered = false;
|
|
592
|
+
}
|
|
593
|
+
if (delivered && cliBridgeEnabledOf(scope.getSnapshot().value)) return;
|
|
594
|
+
throw hostError instanceof Error ? hostError : new WorkBuddySettingsWriteError("cliBridge", "neither the Host save endpoint nor the settings scope persisted the value");
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
547
597
|
* Write one volatile field, then confirm the value actually landed.
|
|
548
598
|
*
|
|
549
599
|
* ORDER MATTERS, and getting it wrong DELETES DATA. The two writers do not have
|
|
@@ -1014,6 +1064,29 @@ window.__ModuleLoader__.load({
|
|
|
1014
1064
|
*/
|
|
1015
1065
|
const DAYS_AT_MS = 2 * DAY_MS$1;
|
|
1016
1066
|
/**
|
|
1067
|
+
* The recovery form of the same duration: "约 2 小时后恢复".
|
|
1068
|
+
*
|
|
1069
|
+
* The bare duration answers "how long?", but beside a red dot on an account row
|
|
1070
|
+
* it left the most important half unsaid: what happens when it elapses. "约 2
|
|
1071
|
+
* 小时后" reads equally well as "the limit lifts" and as "it expires into
|
|
1072
|
+
* something else", and on a row whose whole job is to say whether the account
|
|
1073
|
+
* can serve, that ambiguity is the question the reader came with.
|
|
1074
|
+
*
|
|
1075
|
+
* Same numbers, same rounding, same empty-string contract as
|
|
1076
|
+
* {@link remainingText} — this only appends the verb. Kept as a separate
|
|
1077
|
+
* function rather than a parameter so the two callers that must stay verbless
|
|
1078
|
+
* (the card's "之后可再用" sentence, which already contains its own verb) cannot
|
|
1079
|
+
* accidentally grow a second one.
|
|
1080
|
+
*/
|
|
1081
|
+
function recoversInText(t, untilMs, nowMs) {
|
|
1082
|
+
const left = untilMs - nowMs;
|
|
1083
|
+
if (left <= 0) return "";
|
|
1084
|
+
if (left < MINUTE_MS$1) return t("row.recoversImminent");
|
|
1085
|
+
if (left < HOUR_MS$1) return t("row.recoversMinutes", { count: Math.round(left / MINUTE_MS$1) });
|
|
1086
|
+
if (left < DAYS_AT_MS) return t("row.recoversHours", { count: Math.round(left / HOUR_MS$1) });
|
|
1087
|
+
return t("row.recoversDays", { count: Math.round(left / DAY_MS$1) });
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1017
1090
|
* A short "约 N 分钟后 / 约 N 小时后 / 约 N 天后", or `''` once the moment passed.
|
|
1018
1091
|
*
|
|
1019
1092
|
* The empty string is the contract callers depend on: an elapsed cooldown means
|
|
@@ -1039,6 +1112,29 @@ window.__ModuleLoader__.load({
|
|
|
1039
1112
|
function outcomeOk(outcome) {
|
|
1040
1113
|
return outcome === "ok";
|
|
1041
1114
|
}
|
|
1115
|
+
/**
|
|
1116
|
+
* The MARK form of one probe outcome: the verdict alone, for a slot that cannot
|
|
1117
|
+
* hold an explanation (issue #108).
|
|
1118
|
+
*
|
|
1119
|
+
* `outcomeText` is the right function wherever the reader has room — the pool
|
|
1120
|
+
* card's probe column, the test log — and there the extra sentence earns its
|
|
1121
|
+
* width. The composer panel is a different slot: one line, beside an account
|
|
1122
|
+
* name, in a column about 180 px wide. `row.probeChannelRejected` is 88
|
|
1123
|
+
* characters in Chinese and 179 in English, so it could never fit; with
|
|
1124
|
+
* `nowrap` + `overflow:hidden` on the row it was cut mid-sentence, which the
|
|
1125
|
+
* reporter read as broken rendering.
|
|
1126
|
+
*
|
|
1127
|
+
* So this function returns the SHORT label where one is declared and falls back
|
|
1128
|
+
* to {@link outcomeText} otherwise. The full sentence is never lost: the row's
|
|
1129
|
+
* `title` carries `availabilityLine`, which keeps every word and the absolute
|
|
1130
|
+
* instant, and the pool card still prints it in full.
|
|
1131
|
+
*/
|
|
1132
|
+
function outcomeMarkText(t, outcome) {
|
|
1133
|
+
switch (outcome) {
|
|
1134
|
+
case "channel-rejected": return t("row.probeChannelRejectedShort");
|
|
1135
|
+
default: return outcomeText(t, outcome);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1042
1138
|
/** A short, localizable label for one probe outcome. */
|
|
1043
1139
|
function outcomeText(t, outcome) {
|
|
1044
1140
|
switch (outcome) {
|
|
@@ -1123,11 +1219,11 @@ window.__ModuleLoader__.load({
|
|
|
1123
1219
|
const probe = account.probe;
|
|
1124
1220
|
if (probe !== void 0) {
|
|
1125
1221
|
if (probe.retryAtMs !== void 0) {
|
|
1126
|
-
const left =
|
|
1127
|
-
return left === "" ?
|
|
1222
|
+
const left = recoversInText(t, probe.retryAtMs, nowMs);
|
|
1223
|
+
return left === "" ? outcomeMarkText(t, probe.outcome) : `${outcomeMarkText(t, probe.outcome)} · ${left}`;
|
|
1128
1224
|
}
|
|
1129
|
-
if (probe.outcome === "rate-limited" || probe.outcome === "model-busy" || probe.outcome === "out-of-credit") return `${
|
|
1130
|
-
return
|
|
1225
|
+
if (probe.outcome === "rate-limited" || probe.outcome === "model-busy" || probe.outcome === "out-of-credit") return `${outcomeMarkText(t, probe.outcome)} · ${t("row.poolRetryUnknown")}`;
|
|
1226
|
+
return outcomeMarkText(t, probe.outcome);
|
|
1131
1227
|
}
|
|
1132
1228
|
if (account.excludedBy !== void 0) return exclusionLabel(t, account.excludedBy);
|
|
1133
1229
|
}
|
|
@@ -4154,7 +4250,7 @@ window.__ModuleLoader__.load({
|
|
|
4154
4250
|
CONTRAST colour, so a ticked box painted itself as a heavy black pill — the
|
|
4155
4251
|
loudest object in a section made of plain 13px text. */
|
|
4156
4252
|
.dsm-workbuddy-pref input{flex:none;cursor:pointer;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
4157
|
-
.dsm-workbuddy-pref-check,.dsm-workbuddy-image-tool-check{inline-size:15px;block-size:15px;margin:3px 0 0}
|
|
4253
|
+
.dsm-workbuddy-pref-check,.dsm-workbuddy-image-tool-check,.dsm-workbuddy-cli-bridge-check{inline-size:15px;block-size:15px;margin:3px 0 0}
|
|
4158
4254
|
.dsm-workbuddy-pref input:disabled{cursor:default}
|
|
4159
4255
|
.dsm-workbuddy-pref:has(input:disabled){opacity:.6;cursor:default}
|
|
4160
4256
|
/* The NAME and what it does are TWO lines, not one wrapped blob: first what the
|
|
@@ -4858,9 +4954,20 @@ window.__ModuleLoader__.load({
|
|
|
4858
4954
|
.dsm-workbuddy-composer-panel-mark{
|
|
4859
4955
|
display:flex;flex-wrap:wrap;align-items:baseline;
|
|
4860
4956
|
font-size:11px;line-height:15px;
|
|
4957
|
+
/* WRAP, do not clip (issue #108). The switch above sets white-space:nowrap
|
|
4958
|
+
and overflow:hidden for the NAME, which must stay on one line and ellipsise.
|
|
4959
|
+
Inherited here, those two rules cut the reason mark mid-sentence with no
|
|
4960
|
+
ellipsis at all — the reporter saw "…不是这个账号—" and read it as broken
|
|
4961
|
+
rendering, because a hard cut carries no signal that more exists. The mark
|
|
4962
|
+
is the one part of this row whose length is NOT under the layout's control
|
|
4963
|
+
(it is a translated sentence, and the two locales differ by 2x), so it
|
|
4964
|
+
wraps instead: an extra line is a legible outcome, a severed stroke is not.
|
|
4965
|
+
overflow-wrap:anywhere because Chinese has no spaces to break at. */
|
|
4966
|
+
white-space:normal;
|
|
4967
|
+
overflow-wrap:anywhere;
|
|
4861
4968
|
}
|
|
4862
4969
|
.dsm-workbuddy-composer-panel-mark-current{color:var(--dsw-alias-state-success-primary,#22a06b)}
|
|
4863
|
-
.dsm-workbuddy-composer-panel-mark-reason{color:var(--dsw-alias-state-warn-primary,#f59e0b)}
|
|
4970
|
+
.dsm-workbuddy-composer-panel-mark-reason{color:var(--dsw-alias-state-warn-primary,#f59e0b);min-width:0}
|
|
4864
4971
|
.dsm-workbuddy-composer-panel-mark-current+.dsm-workbuddy-composer-panel-mark-reason::before{
|
|
4865
4972
|
content:" · ";color:var(--dsw-alias-label-dimmed,rgba(127,127,127,.6));
|
|
4866
4973
|
}
|
|
@@ -5369,6 +5476,14 @@ window.__ModuleLoader__.load({
|
|
|
5369
5476
|
*/
|
|
5370
5477
|
const [togglingCredits, setTogglingCredits] = (0, react.useState)(void 0);
|
|
5371
5478
|
/**
|
|
5479
|
+
* The OPTIONAL CodeBuddy CLI route switch (global: one switch, one budget).
|
|
5480
|
+
*
|
|
5481
|
+
* `undefined` until the first Host answer arrives, so the box renders the
|
|
5482
|
+
* committed value instead of guessing — the same rule as `creditsShownOn`.
|
|
5483
|
+
*/
|
|
5484
|
+
const [cliBridgeOn, setCliBridgeOn] = (0, react.useState)(void 0);
|
|
5485
|
+
const [cliBridgeBusy, setCliBridgeBusy] = (0, react.useState)(false);
|
|
5486
|
+
/**
|
|
5372
5487
|
* Probe results, keyed by region then model id.
|
|
5373
5488
|
*
|
|
5374
5489
|
* Kept per region for the same reason drafts are: the two tabs are separate
|
|
@@ -5796,6 +5911,39 @@ window.__ModuleLoader__.load({
|
|
|
5796
5911
|
if (mounted.current) setTogglingCredits(void 0);
|
|
5797
5912
|
}
|
|
5798
5913
|
};
|
|
5914
|
+
/**
|
|
5915
|
+
* Whether the CLI route is mounted.
|
|
5916
|
+
*
|
|
5917
|
+
* Host answer first, settings mirror second, for the same measured reason as
|
|
5918
|
+
* `imageToolOn`: this namespace's browser mirror goes stale on the affected
|
|
5919
|
+
* deployments, and here a stale `true` would claim a spending capability is on.
|
|
5920
|
+
*/
|
|
5921
|
+
const cliBridgeSwitchedOn = () => {
|
|
5922
|
+
if (cliBridgeOn !== void 0) return cliBridgeOn;
|
|
5923
|
+
const fromHost = statusByRegion[activeRegion]?.cliBridgeEnabled;
|
|
5924
|
+
if (typeof fromHost === "boolean") return fromHost;
|
|
5925
|
+
return cliBridgeEnabledOf(settingsScope?.getSnapshot().value);
|
|
5926
|
+
};
|
|
5927
|
+
/**
|
|
5928
|
+
* Flip the global CLI-route switch.
|
|
5929
|
+
*
|
|
5930
|
+
* The Host rebuilds only this route on the change (`cliBridge` is volatile),
|
|
5931
|
+
* so no provider stack is disposed and no in-flight request is interrupted.
|
|
5932
|
+
* Re-reads the usage afterwards so the box shows the COMMITTED value.
|
|
5933
|
+
*/
|
|
5934
|
+
const toggleCliBridge = async (enabled) => {
|
|
5935
|
+
if (settingsScope === void 0) return;
|
|
5936
|
+
setCliBridgeBusy(true);
|
|
5937
|
+
try {
|
|
5938
|
+
await writeCliBridgeEnabled(settingsScope, enabled);
|
|
5939
|
+
if (mounted.current) setCliBridgeOn(enabled);
|
|
5940
|
+
await refreshUsage(activeRegion);
|
|
5941
|
+
} catch (error) {
|
|
5942
|
+
if (mounted.current) setAccountError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
5943
|
+
} finally {
|
|
5944
|
+
if (mounted.current) setCliBridgeBusy(false);
|
|
5945
|
+
}
|
|
5946
|
+
};
|
|
5799
5947
|
const toggleImageTool = async (item, enabled) => {
|
|
5800
5948
|
if (settingsScope === void 0) return;
|
|
5801
5949
|
setTogglingCredits(item);
|
|
@@ -6139,6 +6287,17 @@ window.__ModuleLoader__.load({
|
|
|
6139
6287
|
}
|
|
6140
6288
|
};
|
|
6141
6289
|
/**
|
|
6290
|
+
* Whether ANY speed run is in flight, for the sweep button's disabled state.
|
|
6291
|
+
*
|
|
6292
|
+
* NOT `tpsProbing !== undefined`. `tpsProbing` is a record that is ALWAYS an
|
|
6293
|
+
* object, so that comparison is permanently true and the button was
|
|
6294
|
+
* permanently disabled — the defect this corrects. The other two sweep buttons
|
|
6295
|
+
* compare `sweeping !== undefined` because `sweeping` really is an
|
|
6296
|
+
* `{done,total} | undefined` pair; this map has no such absent state, so the
|
|
6297
|
+
* emptiness of its keys is what "busy" means.
|
|
6298
|
+
*/
|
|
6299
|
+
const tpsBusy = Object.keys(tpsProbing).length > 0;
|
|
6300
|
+
/**
|
|
6142
6301
|
* Sweep speed for the models this region has ENABLED.
|
|
6143
6302
|
*
|
|
6144
6303
|
* Enabled-only rather than the whole catalog: a speed run is three real
|
|
@@ -6303,9 +6462,41 @@ window.__ModuleLoader__.load({
|
|
|
6303
6462
|
})]
|
|
6304
6463
|
})]
|
|
6305
6464
|
}) : null;
|
|
6465
|
+
/**
|
|
6466
|
+
* The CLI-route switch.
|
|
6467
|
+
*
|
|
6468
|
+
* GLOBAL, so it is not gated on the active tab's provider being on — the route
|
|
6469
|
+
* pulls its credential from whichever region still has a signed-in account.
|
|
6470
|
+
* Its own class (not `.dsm-workbuddy-pref-check`) for the same reason the image
|
|
6471
|
+
* box has one: the credit-switch suite's "exactly one switch" selector must
|
|
6472
|
+
* keep resolving to the credit box alone.
|
|
6473
|
+
*/
|
|
6474
|
+
const cliBridgePreference = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
6475
|
+
className: "dsm-workbuddy-pref",
|
|
6476
|
+
title: t("row.cliBridgeHint"),
|
|
6477
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6478
|
+
type: "checkbox",
|
|
6479
|
+
className: "dsm-workbuddy-cli-bridge-check",
|
|
6480
|
+
checked: cliBridgeSwitchedOn(),
|
|
6481
|
+
disabled: !canWrite || saving || poolBusy || cliBridgeBusy,
|
|
6482
|
+
onChange: (event) => {
|
|
6483
|
+
toggleCliBridge(event.target.checked);
|
|
6484
|
+
}
|
|
6485
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6486
|
+
className: "dsm-workbuddy-pref-copy",
|
|
6487
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6488
|
+
className: "dsm-workbuddy-pref-label",
|
|
6489
|
+
children: t("row.cliBridgeLabel")
|
|
6490
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6491
|
+
className: "dsm-workbuddy-pref-hint",
|
|
6492
|
+
children: t("row.cliBridgeHint")
|
|
6493
|
+
})]
|
|
6494
|
+
})]
|
|
6495
|
+
});
|
|
6306
6496
|
const creditPreferences = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6307
6497
|
className: "dsm-workbuddy-prefs",
|
|
6308
6498
|
children: [
|
|
6499
|
+
cliBridgePreference,
|
|
6309
6500
|
imageToolPreference,
|
|
6310
6501
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
6311
6502
|
className: "dsm-workbuddy-pref",
|
|
@@ -6614,7 +6805,7 @@ window.__ModuleLoader__.load({
|
|
|
6614
6805
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6615
6806
|
type: "button",
|
|
6616
6807
|
className: "dsm-btn dsm-btn-outline dsm-workbuddy-models-sweep",
|
|
6617
|
-
disabled: busy || tpsSweeping !== void 0 ||
|
|
6808
|
+
disabled: busy || tpsSweeping !== void 0 || tpsBusy || activeEnabledIds.size === 0,
|
|
6618
6809
|
title: t("row.tpsSweepEnabledHint"),
|
|
6619
6810
|
onClick: sweepTpsEnabledModels,
|
|
6620
6811
|
children: tpsSweeping === void 0 ? t("row.tpsSweepEnabled") : t("row.tpsTesting", {
|
|
@@ -8087,6 +8278,7 @@ window.__ModuleLoader__.load({
|
|
|
8087
8278
|
"row.probeCredentialRejected": "✗ WorkBuddy refused this account's token — sign in again or pick another account",
|
|
8088
8279
|
"row.probePolicyRejected": "✗ WorkBuddy's server refused this request under its content policy — re-signing in won't help; try the desktop app or another region/account",
|
|
8089
8280
|
"row.probeChannelRejected": "✗ The gateway refused the PROMPT itself, not this account — the opening of a system message matched its third-party-agent filter, so another account or region answers the same way",
|
|
8281
|
+
"row.probeChannelRejectedShort": "✗ Gateway refused the prompt",
|
|
8090
8282
|
"row.probeNotFound": "✗ The upstream does not know this model",
|
|
8091
8283
|
"row.probeUnavailable": "✗ The upstream could not be reached — no usable answer came back",
|
|
8092
8284
|
"row.probeFailed": "✗ Test failed",
|
|
@@ -8184,6 +8376,10 @@ window.__ModuleLoader__.load({
|
|
|
8184
8376
|
"row.remainingMinutes": "in about {count} min",
|
|
8185
8377
|
"row.remainingHours": "in about {count} h",
|
|
8186
8378
|
"row.remainingDays": "in about {count} d",
|
|
8379
|
+
"row.recoversImminent": "recovering any moment now",
|
|
8380
|
+
"row.recoversMinutes": "recovers in about {count} min",
|
|
8381
|
+
"row.recoversHours": "recovers in about {count} h",
|
|
8382
|
+
"row.recoversDays": "recovers in about {count} d",
|
|
8187
8383
|
"row.poolProbeJustNow": "just now",
|
|
8188
8384
|
"row.poolProbeMinutesAgo": "{count} min ago",
|
|
8189
8385
|
"row.poolProbeHoursAgo": "{count} h ago",
|
|
@@ -8273,6 +8469,8 @@ window.__ModuleLoader__.load({
|
|
|
8273
8469
|
"row.poolRowRemoved": "{accountName}: hidden from the list. 「Detect accounts again」 re-adds it; the desktop app stays signed in.",
|
|
8274
8470
|
"row.poolRowRemoving": "Removing the account…",
|
|
8275
8471
|
"row.poolRowRemoveDesktopOnly": "{accountName}: hidden from the list — this account comes from the desktop app's own sign-in, which is left untouched. 「Detect accounts again」 re-adds it.",
|
|
8472
|
+
"row.cliBridgeLabel": "Let the local CodeBuddy CLI do the work",
|
|
8473
|
+
"row.cliBridgeHint": "Adds the codebuddy_ask tool and the /codebuddy command. Each call spends CodeBuddy quota (and, with injectResult on, one DSH turn). Off by default.",
|
|
8276
8474
|
"row.imageToolLabel": "Let the model draw images",
|
|
8277
8475
|
"row.imageToolHint": "Adds the workbuddy_draw_image tool, which the MODEL may call on its own — about 5.71 credits per image, with no per-call confirmation. Off means the tool is not registered at all.",
|
|
8278
8476
|
"row.showCreditsCn": "Show credits in the composer toolbar",
|
|
@@ -8446,6 +8644,7 @@ window.__ModuleLoader__.load({
|
|
|
8446
8644
|
"row.probeCredentialRejected": "✗ WorkBuddy 拒绝了这个账号的 token——请重新登录或换一个账号",
|
|
8447
8645
|
"row.probePolicyRejected": "✗ WorkBuddy 服务端按内容策略拒绝了这次请求——重新登录无效;可在桌面端验证或切换区域/账号",
|
|
8448
8646
|
"row.probeChannelRejected": "✗ 网关拦的是提示词本身,不是这个账号——某条 system 消息的开头命中了它的第三方 agent 过滤,换账号或换区域都会得到同一个答案(测试能过、聊天被拒,正是这个原因)",
|
|
8647
|
+
"row.probeChannelRejectedShort": "✗ 网关拦的是提示词",
|
|
8449
8648
|
"row.probeNotFound": "✗ 上游不认识这个模型",
|
|
8450
8649
|
"row.probeUnavailable": "✗ 连不上上游——上游没有给出可用答复",
|
|
8451
8650
|
"row.probeFailed": "✗ 测试失败",
|
|
@@ -8543,6 +8742,10 @@ window.__ModuleLoader__.load({
|
|
|
8543
8742
|
"row.remainingMinutes": "约 {count} 分钟后",
|
|
8544
8743
|
"row.remainingHours": "约 {count} 小时后",
|
|
8545
8744
|
"row.remainingDays": "约 {count} 天后",
|
|
8745
|
+
"row.recoversImminent": "即将恢复",
|
|
8746
|
+
"row.recoversMinutes": "约 {count} 分钟后恢复",
|
|
8747
|
+
"row.recoversHours": "约 {count} 小时后恢复",
|
|
8748
|
+
"row.recoversDays": "约 {count} 天后恢复",
|
|
8546
8749
|
"row.poolProbeJustNow": "刚刚",
|
|
8547
8750
|
"row.poolProbeMinutesAgo": "{count} 分钟前",
|
|
8548
8751
|
"row.poolProbeHoursAgo": "{count} 小时前",
|
|
@@ -8632,6 +8835,8 @@ window.__ModuleLoader__.load({
|
|
|
8632
8835
|
"row.poolRowRemoved": "{accountName}:已从列表中隐藏。点「重新检测账号」会重新加入,桌面 App 的登录不受影响。",
|
|
8633
8836
|
"row.poolRowRemoving": "正在删除账号…",
|
|
8634
8837
|
"row.poolRowRemoveDesktopOnly": "{accountName}:已从列表中隐藏——这个账号来自桌面 App 自己的登录,该登录未被改动。点「重新检测账号」会重新加入。",
|
|
8838
|
+
"row.cliBridgeLabel": "允许调用本机 CodeBuddy CLI 干活",
|
|
8839
|
+
"row.cliBridgeHint": "开启后多出 codebuddy_ask 工具与 /codebuddy 指令;每次调用花 CodeBuddy 配额(injectResult 开着时还会再花一次 DSH token)。默认关闭。",
|
|
8635
8840
|
"row.imageToolLabel": "允许模型自主生图",
|
|
8636
8841
|
"row.imageToolHint": "开启后模型可以自己调用 workbuddy_draw_image 画图——约 5.71 积分/张,没有逐次确认。关闭时该工具根本不会注册。",
|
|
8637
8842
|
"row.showCreditsCn": "在输入框工具栏显示积分读数",
|
|
@@ -5861,7 +5861,7 @@ function generationOf(version) {
|
|
|
5861
5861
|
//#endregion
|
|
5862
5862
|
//#region src/version.ts
|
|
5863
5863
|
/** The npm package version this build was produced from. */
|
|
5864
|
-
const WORKBUDDY_CONNECT_VERSION = "5.
|
|
5864
|
+
const WORKBUDDY_CONNECT_VERSION = "5.3.0";
|
|
5865
5865
|
//#endregion
|
|
5866
5866
|
//#region src/host-heartbeat.ts
|
|
5867
5867
|
/**
|
package/lib/index.d.ts
CHANGED
|
@@ -1556,6 +1556,32 @@ declare class WorkBuddyCatalog {
|
|
|
1556
1556
|
set(models: readonly WorkBuddyModelInfo[]): void;
|
|
1557
1557
|
}
|
|
1558
1558
|
//#endregion
|
|
1559
|
+
//#region src/cli-bridge/mount.d.ts
|
|
1560
|
+
/**
|
|
1561
|
+
* The `cliBridge` settings as they arrive from the config schema.
|
|
1562
|
+
*
|
|
1563
|
+
* Every field is optional because the schema may hand over a partial object, and
|
|
1564
|
+
* a user who edits only one key must not have to restate the rest.
|
|
1565
|
+
*/
|
|
1566
|
+
interface CliBridgeSettings {
|
|
1567
|
+
enabled?: boolean;
|
|
1568
|
+
binary?: string;
|
|
1569
|
+
model?: string;
|
|
1570
|
+
permissionMode?: string;
|
|
1571
|
+
effort?: string;
|
|
1572
|
+
maxTurns?: number;
|
|
1573
|
+
timeoutSecs?: number;
|
|
1574
|
+
regionOrder?: string;
|
|
1575
|
+
workingDir?: string;
|
|
1576
|
+
allowedDirs?: string;
|
|
1577
|
+
appendSystemPrompt?: string;
|
|
1578
|
+
allowUnattended?: boolean;
|
|
1579
|
+
maxReplyChars?: number;
|
|
1580
|
+
injectResult?: boolean;
|
|
1581
|
+
maxTurnsPerSessionHour?: number;
|
|
1582
|
+
maxTurnsPerHour?: number;
|
|
1583
|
+
}
|
|
1584
|
+
//#endregion
|
|
1559
1585
|
//#region src/off-thinking.d.ts
|
|
1560
1586
|
/**
|
|
1561
1587
|
* Ids observed to REFUSE `reasoning_effort: "off"` with HTTP 400 despite
|
|
@@ -3104,6 +3130,17 @@ type WorkBuddyWebUsage =
|
|
|
3104
3130
|
* after a switch-off that never landed.
|
|
3105
3131
|
*/
|
|
3106
3132
|
imageToolEnabled?: boolean;
|
|
3133
|
+
/**
|
|
3134
|
+
* Whether the OPTIONAL CodeBuddy CLI route is mounted (tool `codebuddy_ask`
|
|
3135
|
+
* + command `/codebuddy`).
|
|
3136
|
+
*
|
|
3137
|
+
* GLOBAL, not per region: the route has ONE switch for both regions, so the
|
|
3138
|
+
* same value rides on every region's answer and the card reads it off the
|
|
3139
|
+
* active tab. Absent reads as OFF — this switch authorizes a child process
|
|
3140
|
+
* that edits files and spends CodeBuddy quota, so a Host that cannot answer
|
|
3141
|
+
* must not be read as consent.
|
|
3142
|
+
*/
|
|
3143
|
+
cliBridgeEnabled?: boolean;
|
|
3107
3144
|
/** WHERE this region's readout sits (issue #62); absent means `composer`. */
|
|
3108
3145
|
creditPosition?: WorkBuddyCreditPosition;
|
|
3109
3146
|
message?: string;
|
|
@@ -3149,6 +3186,17 @@ type WorkBuddyWebUsage =
|
|
|
3149
3186
|
* after a switch-off that never landed.
|
|
3150
3187
|
*/
|
|
3151
3188
|
imageToolEnabled?: boolean;
|
|
3189
|
+
/**
|
|
3190
|
+
* Whether the OPTIONAL CodeBuddy CLI route is mounted (tool `codebuddy_ask`
|
|
3191
|
+
* + command `/codebuddy`).
|
|
3192
|
+
*
|
|
3193
|
+
* GLOBAL, not per region: the route has ONE switch for both regions, so the
|
|
3194
|
+
* same value rides on every region's answer and the card reads it off the
|
|
3195
|
+
* active tab. Absent reads as OFF — this switch authorizes a child process
|
|
3196
|
+
* that edits files and spends CodeBuddy quota, so a Host that cannot answer
|
|
3197
|
+
* must not be read as consent.
|
|
3198
|
+
*/
|
|
3199
|
+
cliBridgeEnabled?: boolean;
|
|
3152
3200
|
/** WHERE this region's readout sits (issue #62); absent means `composer`. */
|
|
3153
3201
|
creditPosition?: WorkBuddyCreditPosition;
|
|
3154
3202
|
source?: 'desktop' | 'dsh';
|
|
@@ -3629,6 +3677,19 @@ interface WorkBuddyStatusRouteOptions {
|
|
|
3629
3677
|
* cannot answer must not be read as consent.
|
|
3630
3678
|
*/
|
|
3631
3679
|
imageToolEnabled?(region: WorkBuddyRegion): boolean;
|
|
3680
|
+
/**
|
|
3681
|
+
* Whether the OPTIONAL CodeBuddy CLI route is mounted (`codebuddy_ask` tool +
|
|
3682
|
+
* `/codebuddy` command).
|
|
3683
|
+
*
|
|
3684
|
+
* GLOBAL rather than per region — one switch, one route — so it takes no
|
|
3685
|
+
* argument. Optional, and absent reads as OFF: this switch authorizes a child
|
|
3686
|
+
* process to edit files and spend CodeBuddy quota, so an older Host that
|
|
3687
|
+
* cannot answer must not be read as consent. The card reads it off the Host's
|
|
3688
|
+
* answer for the same measured reason as `imageToolEnabled`: the browser's
|
|
3689
|
+
* settings mirror is stale for this namespace on the affected 0.1.7
|
|
3690
|
+
* deployments, and a stale `true` here would claim a spending capability is on.
|
|
3691
|
+
*/
|
|
3692
|
+
cliBridgeEnabled?(): boolean;
|
|
3632
3693
|
/**
|
|
3633
3694
|
* Send one real-volume request to each named model of a region and report what
|
|
3634
3695
|
* came back.
|
|
@@ -4207,6 +4268,15 @@ interface Config {
|
|
|
4207
4268
|
imageModelIds?: string[];
|
|
4208
4269
|
/** @deprecated See {@link Config.lastCatalog}. */
|
|
4209
4270
|
contextBudgets?: Record<string, WorkBuddyContextBudget>;
|
|
4271
|
+
/**
|
|
4272
|
+
* The optional CLI route: let the locally signed-in CodeBuddy CLI do the work
|
|
4273
|
+
* in a separate agent instead of proxying the gateway.
|
|
4274
|
+
*
|
|
4275
|
+
* It is OFF by default and completely independent of the provider stacks, so a
|
|
4276
|
+
* config that never mentions it behaves exactly as before. This is a
|
|
4277
|
+
* client-fingerprint workaround, not an account one — see `cli-bridge/runner`.
|
|
4278
|
+
*/
|
|
4279
|
+
cliBridge?: CliBridgeSettings;
|
|
4210
4280
|
}
|
|
4211
4281
|
/**
|
|
4212
4282
|
* Mark a schema's field as volatile on the DSH lines that support it.
|
|
@@ -4224,28 +4294,6 @@ interface Config {
|
|
|
4224
4294
|
* moved up — which is exactly how the volatile-path defect below went unseen.
|
|
4225
4295
|
*/
|
|
4226
4296
|
declare function asVolatile<T>(schema: z<T>): z<T>;
|
|
4227
|
-
/**
|
|
4228
|
-
* Deep copy of a config value with every `{get(): T}` live reference replaced
|
|
4229
|
-
* by the value it resolves to.
|
|
4230
|
-
*
|
|
4231
|
-
* {@link unwrapVolatile} only peels the ONE level a caller reads, which is all
|
|
4232
|
-
* the ordinary read paths need. Handing a config object to a settings service
|
|
4233
|
-
* is different: the service validates and `structuredClone`s the WHOLE object,
|
|
4234
|
-
* so a reference surviving anywhere inside it fails schema validation with a
|
|
4235
|
-
* message that names the field but not the cause —
|
|
4236
|
-
* `$.authFile expected string but got [object Object]`.
|
|
4237
|
-
*
|
|
4238
|
-
* That is exactly what happened on the 0.1.5 line once volatile marking became
|
|
4239
|
-
* active: `installSection` received the raw config, whose volatile fields were
|
|
4240
|
-
* live references, and every field it validated threw. The namespace never
|
|
4241
|
-
* registered, so the card's settings silently disappeared.
|
|
4242
|
-
*
|
|
4243
|
-
* The implementation now lives in the node-free host<->client bridge, because
|
|
4244
|
-
* the browser half needs the SAME unwrap before it spreads a resolved field —
|
|
4245
|
-
* spreading a live reference is `{get: <function>}`, which drops every sibling
|
|
4246
|
-
* region. It is imported and re-exported from here so the Host entry keeps
|
|
4247
|
-
* exposing it as part of its public API.
|
|
4248
|
-
*/
|
|
4249
4297
|
declare const Config: z<Config>;
|
|
4250
4298
|
/**
|
|
4251
4299
|
* One region's saved model state. A config written before the region split has
|