dsh-workbuddy-xdpool 1.7.0 → 1.7.2
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 +169 -84
- package/lib/bin.js +444 -42
- package/lib/client.js +168 -10
- package/lib/index.d.ts +270 -4
- package/lib/index.js +485 -68
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -27,10 +27,39 @@ window.__ModuleLoader__.load({
|
|
|
27
27
|
const POOL_RESET_COOLDOWN_PATH = "/plugins/dsh-workbuddy-xdpool/cooldowns/reset";
|
|
28
28
|
/** Plugin-owned daily check-in action endpoint (claim today's reward). */
|
|
29
29
|
const POOL_CHECKIN_PATH = "/plugins/dsh-workbuddy-xdpool/checkin";
|
|
30
|
+
/**
|
|
31
|
+
* Throw one account out of the pool for good, or take it back.
|
|
32
|
+
*
|
|
33
|
+
* Separate from the disable route because the semantics differ: disabling is a
|
|
34
|
+
* rotation preference the account survives, ignoring survives the account.
|
|
35
|
+
*/
|
|
36
|
+
const POOL_ACCOUNT_IGNORE_PATH = "/plugins/dsh-workbuddy-xdpool/accounts/ignored";
|
|
30
37
|
/** Run one automation job immediately, so the card can verify it on demand. */
|
|
31
38
|
const POOL_AUTOMATION_RUN_PATH = "/plugins/dsh-workbuddy-xdpool/automation/run";
|
|
32
39
|
/** Set or clear one account's reserved-credit floor. */
|
|
33
40
|
const POOL_CREDIT_RESERVE_PATH = "/plugins/dsh-workbuddy-xdpool/accounts/credit-reserve";
|
|
41
|
+
/**
|
|
42
|
+
* The schedule every automation job falls back to.
|
|
43
|
+
*
|
|
44
|
+
* Shared by both halves on purpose. The host uses it when a configured hour
|
|
45
|
+
* list arrives empty (the settings schema materializes "never configured" into
|
|
46
|
+
* `[]`), and the card uses it when it writes the `automation` block back, so a
|
|
47
|
+
* document that already holds an empty list is healed instead of being saved
|
|
48
|
+
* back as an unrunnable schedule.
|
|
49
|
+
*
|
|
50
|
+
* This lives here rather than in `scheduler.ts` because the browser half cannot
|
|
51
|
+
* import the host module: `scheduler.ts` pulls in `node:crypto` and the whole
|
|
52
|
+
* upstream client, none of which exists in the browser bundle. Two hand-written
|
|
53
|
+
* copies would drift, and the drift is invisible — the card would write a
|
|
54
|
+
* schedule the scheduler does not run.
|
|
55
|
+
*/
|
|
56
|
+
const DEFAULT_AUTOMATION_HOURS = {
|
|
57
|
+
checkin: [9],
|
|
58
|
+
report: [10],
|
|
59
|
+
tasks: [11],
|
|
60
|
+
streak: [12],
|
|
61
|
+
travel: [9, 21]
|
|
62
|
+
};
|
|
34
63
|
//#endregion
|
|
35
64
|
//#region src/client/icon.ts
|
|
36
65
|
/**
|
|
@@ -168,6 +197,23 @@ window.__ModuleLoader__.load({
|
|
|
168
197
|
.dsm-workbuddy-xdpool-account-toggle:disabled{cursor:default;opacity:.6}
|
|
169
198
|
.dsm-workbuddy-xdpool-account-toggle-on{background:color-mix(in oklab, var(--dsw-alias-state-success-primary,#22a06b) 14%, transparent);border-color:color-mix(in oklab, var(--dsw-alias-state-success-primary,#22a06b) 55%, transparent);color:var(--dsw-alias-state-success-primary,#22a06b);font-weight:600}
|
|
170
199
|
.dsm-workbuddy-xdpool-account-toggle-dot{width:6px;height:6px;border-radius:50%;flex:none;background:currentColor;opacity:.9}
|
|
200
|
+
/* "Remove" button: destructive and reversible, so it is quiet until hovered. */
|
|
201
|
+
.dsm-workbuddy-xdpool-account-ignore{appearance:none;font:inherit;flex:none;cursor:pointer;border:1px solid transparent;border-radius:999px;padding:3px 10px;font-size:11px;line-height:17px;background:transparent;color:var(--dsw-alias-label-tertiary,#9aa0a8);transition:color .16s,border-color .16s,background .16s}
|
|
202
|
+
.dsm-workbuddy-xdpool-account-ignore:hover:not(:disabled){color:var(--dsw-alias-state-error-primary,#ef4444);border-color:color-mix(in oklab, var(--dsw-alias-state-error-primary,#ef4444) 45%, transparent);background:color-mix(in oklab, var(--dsw-alias-state-error-primary,#ef4444) 10%, transparent)}
|
|
203
|
+
.dsm-workbuddy-xdpool-account-ignore:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#5686fe);outline-offset:1px}
|
|
204
|
+
.dsm-workbuddy-xdpool-account-ignore:disabled{cursor:default;opacity:.6}
|
|
205
|
+
/* Ignored-account list: visible proof that "remove" can be undone. */
|
|
206
|
+
.dsm-workbuddy-xdpool-ignored-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid color-mix(in oklab, var(--dsw-alias-border-l2,#3a3d45) 45%, transparent)}
|
|
207
|
+
.dsm-workbuddy-xdpool-ignored-title{margin:0;color:var(--dsw-alias-label-primary,#e6e6e6);font-size:13px;font-weight:600;line-height:19px}
|
|
208
|
+
.dsm-workbuddy-xdpool-ignored-summary{margin:0;color:var(--dsw-alias-label-tertiary,#9aa0a8);font-size:11px;line-height:17px}
|
|
209
|
+
.dsm-workbuddy-xdpool-ignored-list{display:flex;flex-direction:column}
|
|
210
|
+
.dsm-workbuddy-xdpool-ignored-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 16px}
|
|
211
|
+
.dsm-workbuddy-xdpool-ignored-row+.dsm-workbuddy-xdpool-ignored-row{border-top:1px solid color-mix(in oklab, var(--dsw-alias-border-l2,#3a3d45) 30%, transparent)}
|
|
212
|
+
.dsm-workbuddy-xdpool-ignored-label{color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:12px;line-height:18px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
213
|
+
.dsm-workbuddy-xdpool-ignored-restore{appearance:none;font:inherit;flex:none;cursor:pointer;border:1px solid color-mix(in oklab, var(--dsw-alias-border-l2,#3a3d45) 70%, transparent);border-radius:999px;padding:3px 10px;font-size:11px;line-height:17px;background:transparent;color:var(--dsw-alias-label-secondary,#c6c9d0);transition:color .16s,border-color .16s}
|
|
214
|
+
.dsm-workbuddy-xdpool-ignored-restore:hover:not(:disabled){color:var(--dsw-alias-label-primary,#e6e6e6);border-color:var(--dsw-alias-label-dimmed,#777)}
|
|
215
|
+
.dsm-workbuddy-xdpool-ignored-restore:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#5686fe);outline-offset:1px}
|
|
216
|
+
.dsm-workbuddy-xdpool-ignored-restore:disabled{cursor:default;opacity:.6}
|
|
171
217
|
.dsm-workbuddy-xdpool-account-tags{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
|
|
172
218
|
.dsm-workbuddy-xdpool-account-tag{padding:1px 8px;border-radius:999px;font-size:11px;line-height:18px;background:var(--dsw-alias-state-success-subtle,rgba(34,160,107,.12));color:var(--dsw-alias-state-success-primary,#22a06b)}
|
|
173
219
|
.dsm-workbuddy-xdpool-account-tag-cooling{background:var(--dsw-alias-state-warning-subtle,rgba(217,119,6,.15));color:var(--dsw-alias-state-warning-primary,#d97706)}
|
|
@@ -391,6 +437,17 @@ window.__ModuleLoader__.load({
|
|
|
391
437
|
"streak",
|
|
392
438
|
"travel"
|
|
393
439
|
];
|
|
440
|
+
/**
|
|
441
|
+
* The hour list to save for one job: what the card holds, or the default.
|
|
442
|
+
*
|
|
443
|
+
* Mirrors the host's own fallback (`hoursOrDefault` in `scheduler.ts`). An
|
|
444
|
+
* empty list must resolve to the default on BOTH sides, or the card would save
|
|
445
|
+
* a schedule the scheduler then refuses to run — the exact silent standstill
|
|
446
|
+
* this pair of fixes exists to remove.
|
|
447
|
+
*/
|
|
448
|
+
function hoursOrDefault(configured, fallback) {
|
|
449
|
+
return configured !== void 0 && configured.length > 0 ? [...configured] : [...fallback];
|
|
450
|
+
}
|
|
394
451
|
/** Read one job's configured hours off the status document. */
|
|
395
452
|
function automationHours(status, kind) {
|
|
396
453
|
const automation = status.automation;
|
|
@@ -473,9 +530,21 @@ window.__ModuleLoader__.load({
|
|
|
473
530
|
const days = daysUntil(pack.expiresAtMs);
|
|
474
531
|
return days !== void 0 && days <= 3;
|
|
475
532
|
}
|
|
533
|
+
/**
|
|
534
|
+
* The promo badge for one model, or undefined when it has none.
|
|
535
|
+
*
|
|
536
|
+
* `free` is read off the CREDIT MULTIPLIER, not off a tag. Neither gateway ever
|
|
537
|
+
* sends a literal `free` tag: the global roster marks its zero-cost models
|
|
538
|
+
* (`hy3`, `hy4-preview-f`, `deepseek-v4.1-flash`) as `credits: "x0.00"`, so
|
|
539
|
+
* waiting for a tag meant the badge NEVER appeared — including on models that
|
|
540
|
+
* genuinely cost nothing.
|
|
541
|
+
*
|
|
542
|
+
* An explicit free-ish tag still wins when present, so a gateway that starts
|
|
543
|
+
* tagging them keeps working without another change.
|
|
544
|
+
*/
|
|
476
545
|
function tagFor(model) {
|
|
477
546
|
const tags = model.tags ?? [];
|
|
478
|
-
if (tags.includes("free")) return "free";
|
|
547
|
+
if (tags.includes("free") || model.multiplier === 0) return "free";
|
|
479
548
|
if (tags.includes("limited-free")) return "limited";
|
|
480
549
|
if (tags.includes("night-discount")) return "night";
|
|
481
550
|
}
|
|
@@ -687,6 +756,37 @@ window.__ModuleLoader__.load({
|
|
|
687
756
|
if (mounted.current) setAccountBusyId(void 0);
|
|
688
757
|
}
|
|
689
758
|
};
|
|
759
|
+
/**
|
|
760
|
+
* Throw one account out of the pool for good, or take it back.
|
|
761
|
+
*
|
|
762
|
+
* The host owns the ignore file, so this is a plain route call: no settings
|
|
763
|
+
* scope is involved, which is also why it keeps working on a profile whose
|
|
764
|
+
* settings section is read-only.
|
|
765
|
+
*/
|
|
766
|
+
const setAccountIgnored = async (accountId, ignored) => {
|
|
767
|
+
setAccountBusyId(accountId);
|
|
768
|
+
setFlash(void 0);
|
|
769
|
+
try {
|
|
770
|
+
const response = await fetch(POOL_ACCOUNT_IGNORE_PATH, {
|
|
771
|
+
method: "POST",
|
|
772
|
+
headers: { "Content-Type": "application/json" },
|
|
773
|
+
body: JSON.stringify({
|
|
774
|
+
accountId,
|
|
775
|
+
ignored
|
|
776
|
+
})
|
|
777
|
+
});
|
|
778
|
+
if (!response.ok) {
|
|
779
|
+
const detail = await response.json().catch(() => ({}));
|
|
780
|
+
throw new Error(detail.error ?? `HTTP ${response.status}`);
|
|
781
|
+
}
|
|
782
|
+
await refresh(activeRegion);
|
|
783
|
+
} catch (cause) {
|
|
784
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
785
|
+
if (mounted.current) setError(t?.("row.accountIgnoreError", { message }) ?? "Could not change the ignore list: " + message);
|
|
786
|
+
} finally {
|
|
787
|
+
if (mounted.current) setAccountBusyId(void 0);
|
|
788
|
+
}
|
|
789
|
+
};
|
|
690
790
|
/** Keep the draft in step with the server copy while nothing is dirty. */
|
|
691
791
|
const modelDraft = draft ?? (status === void 0 ? {} : draftFromStatus(status));
|
|
692
792
|
/** Model edits need a writable settings scope; otherwise the rows are read-only. */
|
|
@@ -790,12 +890,11 @@ window.__ModuleLoader__.load({
|
|
|
790
890
|
setFlash(void 0);
|
|
791
891
|
try {
|
|
792
892
|
await write.call(settingsScope, "automation", {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
},
|
|
893
|
+
checkinHours: hoursOrDefault(existing?.checkinHours, DEFAULT_AUTOMATION_HOURS.checkin),
|
|
894
|
+
reportHours: hoursOrDefault(existing?.reportHours, DEFAULT_AUTOMATION_HOURS.report),
|
|
895
|
+
taskHours: hoursOrDefault(existing?.taskHours, DEFAULT_AUTOMATION_HOURS.tasks),
|
|
896
|
+
streakHours: hoursOrDefault(existing?.streakHours, DEFAULT_AUTOMATION_HOURS.streak),
|
|
897
|
+
travelHours: hoursOrDefault(existing?.travelHours, DEFAULT_AUTOMATION_HOURS.travel),
|
|
799
898
|
enabled
|
|
800
899
|
});
|
|
801
900
|
await refresh(activeRegion);
|
|
@@ -1171,7 +1270,7 @@ window.__ModuleLoader__.load({
|
|
|
1171
1270
|
}),
|
|
1172
1271
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1173
1272
|
className: "dsm-workbuddy-xdpool-auto-job-last",
|
|
1174
|
-
children: job?.
|
|
1273
|
+
children: job?.lastRunAtMs === void 0 ? t?.("row.autoNever") ?? "not run yet" : `${formatTime(job.lastRunAtMs)} · ${job.ok}${job.failed > 0 ? `/${job.failed}` : ""}`
|
|
1175
1274
|
}),
|
|
1176
1275
|
job?.progress === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1177
1276
|
className: "dsm-workbuddy-xdpool-auto-job-note",
|
|
@@ -1272,11 +1371,46 @@ window.__ModuleLoader__.load({
|
|
|
1272
1371
|
onToggleDisabled: (accountId, disabled) => {
|
|
1273
1372
|
toggleAccountDisabled(accountId, disabled);
|
|
1274
1373
|
},
|
|
1374
|
+
onIgnoreAccount: (accountId) => {
|
|
1375
|
+
setAccountIgnored(accountId, true);
|
|
1376
|
+
},
|
|
1275
1377
|
...accountBusyId === void 0 ? {} : { accountBusyId },
|
|
1276
1378
|
t
|
|
1277
1379
|
}, account.id))
|
|
1278
1380
|
]
|
|
1279
1381
|
}) : null,
|
|
1382
|
+
(status?.ignored.length ?? 0) > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1383
|
+
className: "dsm-workbuddy-xdpool-card dsm-workbuddy-xdpool-ignored",
|
|
1384
|
+
"aria-label": t?.("row.ignoredTitle") ?? "Removed accounts",
|
|
1385
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1386
|
+
className: "dsm-workbuddy-xdpool-ignored-head",
|
|
1387
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
1388
|
+
className: "dsm-workbuddy-xdpool-ignored-title",
|
|
1389
|
+
children: t?.("row.ignoredTitle") ?? "Removed accounts"
|
|
1390
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1391
|
+
className: "dsm-workbuddy-xdpool-ignored-summary",
|
|
1392
|
+
children: t?.("row.ignoredSummary", { count: status?.ignored.length ?? 0 }) ?? `${status?.ignored.length ?? 0} account(s) no longer in the pool`
|
|
1393
|
+
})]
|
|
1394
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1395
|
+
className: "dsm-workbuddy-xdpool-ignored-list",
|
|
1396
|
+
children: (status?.ignored ?? []).map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1397
|
+
className: "dsm-workbuddy-xdpool-ignored-row",
|
|
1398
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1399
|
+
className: "dsm-workbuddy-xdpool-ignored-label",
|
|
1400
|
+
children: entry.label
|
|
1401
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1402
|
+
type: "button",
|
|
1403
|
+
className: "dsm-workbuddy-xdpool-ignored-restore",
|
|
1404
|
+
title: t?.("row.ignoredRestoreHint") ?? "Put this account back into the pool",
|
|
1405
|
+
disabled: accountBusyId === entry.id,
|
|
1406
|
+
onClick: () => {
|
|
1407
|
+
setAccountIgnored(entry.id, false);
|
|
1408
|
+
},
|
|
1409
|
+
children: t?.("row.ignoredRestore") ?? "Restore"
|
|
1410
|
+
})]
|
|
1411
|
+
}, entry.id))
|
|
1412
|
+
})]
|
|
1413
|
+
}) : null,
|
|
1280
1414
|
(status?.models.length ?? 0) > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1281
1415
|
className: "dsm-workbuddy-xdpool-card dsm-workbuddy-xdpool-models",
|
|
1282
1416
|
"aria-label": t?.("row.modelsTitle") ?? "Models",
|
|
@@ -1332,7 +1466,7 @@ window.__ModuleLoader__.load({
|
|
|
1332
1466
|
});
|
|
1333
1467
|
}
|
|
1334
1468
|
/** One account block: label + status tag + meta + optional credit panels. */
|
|
1335
|
-
function AccountBlock({ account, t, checkinBusyId, onClaimCheckin, accountBusyId, onToggleDisabled, onSaveCreditReserve, reserveBusyId }) {
|
|
1469
|
+
function AccountBlock({ account, t, checkinBusyId, onClaimCheckin, accountBusyId, onToggleDisabled, onIgnoreAccount, onSaveCreditReserve, reserveBusyId }) {
|
|
1336
1470
|
const isDisabled = account.disabled === true;
|
|
1337
1471
|
const isCooling = account.cooling === true;
|
|
1338
1472
|
const cooldownUntil = account.cooldownUntil !== void 0 ? Date.parse(account.cooldownUntil) : void 0;
|
|
@@ -1365,6 +1499,16 @@ window.__ModuleLoader__.load({
|
|
|
1365
1499
|
onToggleDisabled(account.id, !isDisabled);
|
|
1366
1500
|
},
|
|
1367
1501
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dsm-workbuddy-xdpool-account-toggle-dot" }), isDisabled ? t?.("row.accountOff") ?? "Disabled" : t?.("row.accountInRotation") ?? "Enabled"]
|
|
1502
|
+
}),
|
|
1503
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1504
|
+
type: "button",
|
|
1505
|
+
className: "dsm-workbuddy-xdpool-account-ignore",
|
|
1506
|
+
title: t?.("row.accountIgnoreHint") ?? "Remove this account from the pool for good",
|
|
1507
|
+
disabled: accountBusyId === account.id,
|
|
1508
|
+
onClick: () => {
|
|
1509
|
+
onIgnoreAccount(account.id);
|
|
1510
|
+
},
|
|
1511
|
+
children: t?.("row.accountIgnore") ?? "Remove"
|
|
1368
1512
|
})
|
|
1369
1513
|
]
|
|
1370
1514
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -1682,7 +1826,7 @@ window.__ModuleLoader__.load({
|
|
|
1682
1826
|
className: "dsm-workbuddy-xdpool-model-copy",
|
|
1683
1827
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1684
1828
|
className: "dsm-workbuddy-xdpool-model-name",
|
|
1685
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name }), model.multiplier === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1829
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name }), model.multiplier === void 0 || model.multiplier === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1686
1830
|
className: "dsm-workbuddy-xdpool-model-name-rate",
|
|
1687
1831
|
children: t?.("row.rate", { rate: model.multiplier.toFixed(2) }) ?? `${model.multiplier.toFixed(2)}x`
|
|
1688
1832
|
})]
|
|
@@ -1829,6 +1973,13 @@ window.__ModuleLoader__.load({
|
|
|
1829
1973
|
"row.accountOff": "Disabled",
|
|
1830
1974
|
"row.accountToggleHint": "Enable this account (uncheck to keep it out of the pool)",
|
|
1831
1975
|
"row.accountToggleError": "Could not switch the account: {message}",
|
|
1976
|
+
"row.accountIgnore": "Remove",
|
|
1977
|
+
"row.accountIgnoreHint": "Remove this account from the pool for good — its credential stops being read and it will not come back",
|
|
1978
|
+
"row.accountIgnoreError": "Could not change the ignore list: {message}",
|
|
1979
|
+
"row.ignoredTitle": "Removed accounts",
|
|
1980
|
+
"row.ignoredSummary": "{count} account(s) no longer in the pool",
|
|
1981
|
+
"row.ignoredRestore": "Restore",
|
|
1982
|
+
"row.ignoredRestoreHint": "Put this account back into the pool",
|
|
1832
1983
|
"row.currentAccount": "In use now",
|
|
1833
1984
|
"row.currentAccountDisabled": "switched off — the next request moves on",
|
|
1834
1985
|
"row.cooling": "Cooling (rate-limited)",
|
|
@@ -1961,6 +2112,13 @@ window.__ModuleLoader__.load({
|
|
|
1961
2112
|
"row.accountOff": "已停用",
|
|
1962
2113
|
"row.accountToggleHint": "启用该账号(取消勾选则不参与池子)",
|
|
1963
2114
|
"row.accountToggleError": "切换账号失败:{message}",
|
|
2115
|
+
"row.accountIgnore": "移出池子",
|
|
2116
|
+
"row.accountIgnoreHint": "把这个账号永久移出池子 —— 不再读取它的凭据,即使重新登录也不会回来",
|
|
2117
|
+
"row.accountIgnoreError": "修改忽略列表失败:{message}",
|
|
2118
|
+
"row.ignoredTitle": "已移出的账号",
|
|
2119
|
+
"row.ignoredSummary": "{count} 个账号已不在池中",
|
|
2120
|
+
"row.ignoredRestore": "恢复",
|
|
2121
|
+
"row.ignoredRestoreHint": "把这个账号放回池子",
|
|
1964
2122
|
"row.currentAccount": "当前使用",
|
|
1965
2123
|
"row.currentAccountDisabled": "已停用 —— 下次请求会换号",
|
|
1966
2124
|
"row.cooling": "冷却中(被限流)",
|
package/lib/index.d.ts
CHANGED
|
@@ -221,6 +221,21 @@ interface WorkBuddyUpstreamModel {
|
|
|
221
221
|
descriptionZh?: string;
|
|
222
222
|
descriptionEn?: string;
|
|
223
223
|
supportsToolCall?: boolean;
|
|
224
|
+
/**
|
|
225
|
+
* Promo tags the upstream attaches to a model.
|
|
226
|
+
*
|
|
227
|
+
* Both gateways send a `tags` array, but the vocabularies are NOT the same
|
|
228
|
+
* and neither uses the words this plugin used to expect:
|
|
229
|
+
*
|
|
230
|
+
* - Global sends `["craft"]`, `["text-to-image"]`, `["text-to-video"]`, `[]`
|
|
231
|
+
* — capability/grouping labels, never `free`.
|
|
232
|
+
* - Zero cost is expressed as `credits: "x0.00"` instead.
|
|
233
|
+
*
|
|
234
|
+
* So this field is a passthrough of what the upstream really said, and
|
|
235
|
+
* `free` is DERIVED from the multiplier rather than awaited as a tag (see
|
|
236
|
+
* {@link isFreeModel}).
|
|
237
|
+
*/
|
|
238
|
+
tags?: readonly string[];
|
|
224
239
|
}
|
|
225
240
|
/** One billing package, already normalised. */
|
|
226
241
|
interface WorkBuddyCreditPackage {
|
|
@@ -830,6 +845,21 @@ export declare class WorkBuddyAccountPool {
|
|
|
830
845
|
* lives on the pool and is re-applied from settings after each scan.
|
|
831
846
|
*/
|
|
832
847
|
private disabledIds;
|
|
848
|
+
/**
|
|
849
|
+
* Account ids the user threw out of the pool for good.
|
|
850
|
+
*
|
|
851
|
+
* Enforced BEFORE the credential is parsed: `scan()` skips a file whose
|
|
852
|
+
* identity is already ignored, so an ignored account costs no at-rest key
|
|
853
|
+
* lookup (which spawns the desktop app on 5.6.0+) and cannot re-enter the pool
|
|
854
|
+
* when the app writes a fresh sign-in for it. That is the difference from
|
|
855
|
+
* {@link disabledIds}, which only filters at pick time and leaves the account
|
|
856
|
+
* listed, readable and re-discoverable.
|
|
857
|
+
*
|
|
858
|
+
* The set is supplied by the host from the plugin's own ignore file, and is
|
|
859
|
+
* replaced wholesale on every {@link applyIgnored} so removing an entry takes
|
|
860
|
+
* effect on the next scan without a restart.
|
|
861
|
+
*/
|
|
862
|
+
private ignoredIds;
|
|
833
863
|
/**
|
|
834
864
|
* Per-account credit floor, keyed by account id. 0 (or absent) means "spend
|
|
835
865
|
* it all".
|
|
@@ -875,6 +905,19 @@ export declare class WorkBuddyAccountPool {
|
|
|
875
905
|
/** Per-account credit floor, keyed by account id. Absent keeps the current map. */
|
|
876
906
|
creditReserves?: Readonly<Record<string, number>>;
|
|
877
907
|
}): void;
|
|
908
|
+
/**
|
|
909
|
+
* Replace the permanent ignore list.
|
|
910
|
+
*
|
|
911
|
+
* Also drops any already-discovered account that is now ignored, so the change
|
|
912
|
+
* is visible without waiting for the next scan: the card refreshes its status
|
|
913
|
+
* document right after the write, and an account still sitting in `accounts`
|
|
914
|
+
* would keep showing up there.
|
|
915
|
+
*/
|
|
916
|
+
applyIgnored(ids: Iterable<string>): void;
|
|
917
|
+
/** Whether this account has been thrown out of the pool for good. */
|
|
918
|
+
isIgnored(accountId: string): boolean;
|
|
919
|
+
/** Every ignored id currently in force, in insertion order. */
|
|
920
|
+
ignoredIdsInOrder(): string[];
|
|
878
921
|
/** Rescan the auth directories and merge newly discovered accounts. */
|
|
879
922
|
scan(): Promise<WorkBuddyAccount[]>;
|
|
880
923
|
/** All accounts, cooldown state included. */
|
|
@@ -1036,7 +1079,20 @@ interface WorkBuddyModelInfo {
|
|
|
1036
1079
|
/** Upstream tags: free / limited-free / night-discount. */
|
|
1037
1080
|
tags?: readonly string[];
|
|
1038
1081
|
}
|
|
1039
|
-
/**
|
|
1082
|
+
/**
|
|
1083
|
+
* Static fallback used before the first live catalog fetch, and whenever the
|
|
1084
|
+
* upstream cannot be reached.
|
|
1085
|
+
*
|
|
1086
|
+
* The multipliers are carried on purpose. Without them the provider's model
|
|
1087
|
+
* picker silently loses every rate and every free badge the moment the live
|
|
1088
|
+
* fetch fails — which reads to the user as "the plugin broke my model list"
|
|
1089
|
+
* rather than "the upstream is unreachable". The values are the ones the two
|
|
1090
|
+
* gateways actually advertise for these ids (`credits: "x0.79 credits"` and so
|
|
1091
|
+
* on), so a fallback row looks the same as a live one.
|
|
1092
|
+
*
|
|
1093
|
+
* `multiplier: 0` is the gateways' own spelling of "free" (`credits: "x0.00"`),
|
|
1094
|
+
* which is what turns on the free badge.
|
|
1095
|
+
*/
|
|
1040
1096
|
export declare const FALLBACK_WORKBUDDY_MODELS: readonly WorkBuddyModelInfo[];
|
|
1041
1097
|
/** Live catalog with a static fallback behind it. */
|
|
1042
1098
|
export declare class WorkBuddyCatalog {
|
|
@@ -1209,6 +1265,34 @@ interface AutomationJobState {
|
|
|
1209
1265
|
* repeat tick inside the same hour is still refused.
|
|
1210
1266
|
*/
|
|
1211
1267
|
lastRunSlot?: string;
|
|
1268
|
+
/**
|
|
1269
|
+
* Every configured slot consumed TODAY, as `YYYY-MM-DDTHH`.
|
|
1270
|
+
*
|
|
1271
|
+
* This is what actually gates a re-run, and it is a SET rather than a single
|
|
1272
|
+
* slot because one field could not express the contract: a job configured for
|
|
1273
|
+
* `[9, 21]` runs twice, and a single "last slot" value can only remember one
|
|
1274
|
+
* of them — the second run erased the first, so the 9 o'clock candidate looked
|
|
1275
|
+
* unconsumed again and the job re-fired every hour after 21:00.
|
|
1276
|
+
*
|
|
1277
|
+
* The values are the CONFIGURED hours that were spent, never the clock time
|
|
1278
|
+
* the run happened to finish at. Storing the finish time was the original
|
|
1279
|
+
* defect: the reader compared it against a configured candidate, so the two
|
|
1280
|
+
* almost never matched and the gate stayed open all day.
|
|
1281
|
+
*
|
|
1282
|
+
* In-memory like the rest of `states`: this is a per-process record, and the
|
|
1283
|
+
* catch-up design deliberately re-runs an hour that passed while DSH was
|
|
1284
|
+
* closed. See `automationEarnings` for the ledger that DOES persist.
|
|
1285
|
+
*/
|
|
1286
|
+
firedSlots?: readonly string[];
|
|
1287
|
+
/**
|
|
1288
|
+
* The clock slot the last run STARTED in (`YYYY-MM-DDTHH`).
|
|
1289
|
+
*
|
|
1290
|
+
* Separate from {@link firedSlots} on purpose: this is a throttle ("do not
|
|
1291
|
+
* start twice inside the same hour"), while `firedSlots` is the schedule
|
|
1292
|
+
* ledger. Conflating the two is what let a catch-up run at 13:00 erase the
|
|
1293
|
+
* record of the 9 o'clock slot.
|
|
1294
|
+
*/
|
|
1295
|
+
lastFiredHour?: string;
|
|
1212
1296
|
/** Epoch ms of the last completed run. */
|
|
1213
1297
|
lastRunAtMs?: number;
|
|
1214
1298
|
/** Accounts that completed without throwing. */
|
|
@@ -1479,7 +1563,27 @@ export declare class WorkBuddyScheduler {
|
|
|
1479
1563
|
* two hours still runs twice a day — but a job whose hour passed while DSH was
|
|
1480
1564
|
* closed runs immediately on the next tick instead of waiting for tomorrow.
|
|
1481
1565
|
*/
|
|
1482
|
-
|
|
1566
|
+
/**
|
|
1567
|
+
* The configured slot `kind` should consume at `now`, or undefined when none.
|
|
1568
|
+
*
|
|
1569
|
+
* Returns the SLOT STRING (not a boolean) because the caller must record the
|
|
1570
|
+
* same value it acted on. Returning a boolean was the original bug's enabler:
|
|
1571
|
+
* the tick asked "is it due", then `runJob` independently wrote "what time is
|
|
1572
|
+
* it now" — and those two answers were almost never equal.
|
|
1573
|
+
*
|
|
1574
|
+
* CATCH-UP semantics are deliberate: a candidate fires once its hour has
|
|
1575
|
+
* PASSED and its slot is still unconsumed, so a laptop that slept through
|
|
1576
|
+
* 10:00 still runs the job when it wakes, on the same day.
|
|
1577
|
+
*
|
|
1578
|
+
* The EARLIEST unconsumed candidate wins, which is what keeps a two-hour job
|
|
1579
|
+
* (`travelHours: [9, 21]`) whole: consuming the earliest due slot leaves the
|
|
1580
|
+
* later one for its own hour.
|
|
1581
|
+
*/
|
|
1582
|
+
private dueSlot;
|
|
1583
|
+
/** Today's consumed slots for one job, as a set. */
|
|
1584
|
+
private firedSlotsOf;
|
|
1585
|
+
/** Record one consumed slot on a job's state. */
|
|
1586
|
+
private consumeSlot;
|
|
1483
1587
|
private tick;
|
|
1484
1588
|
/** Run one job against every eligible account and record the outcome. */
|
|
1485
1589
|
/**
|
|
@@ -1512,6 +1616,12 @@ export declare class WorkBuddyScheduler {
|
|
|
1512
1616
|
/**
|
|
1513
1617
|
* Run one job against every eligible account and record the outcome.
|
|
1514
1618
|
*
|
|
1619
|
+
* `consumedSlot` is the configured slot this run spends (`dueSlot`'s answer).
|
|
1620
|
+
* It is passed IN rather than recomputed here so the value recorded is exactly
|
|
1621
|
+
* the value the schedule decided on — the defect this replaces wrote
|
|
1622
|
+
* `slotKey(now)` instead, i.e. the clock time the run finished at, which
|
|
1623
|
+
* almost never equals the configured candidate the gate had compared against.
|
|
1624
|
+
*
|
|
1515
1625
|
* The task job runs in TWO passes. The first sends the event chains that light
|
|
1516
1626
|
* up client-scored tasks; the second collects rewards. They are separate
|
|
1517
1627
|
* because scoring lands asynchronously — a chain sent and claimed within the
|
|
@@ -1692,11 +1802,18 @@ export declare const POOL_RESET_COOLDOWN_PATH = "/plugins/dsh-workbuddy-xdpool/c
|
|
|
1692
1802
|
export declare const POOL_CHECKIN_PATH = "/plugins/dsh-workbuddy-xdpool/checkin";
|
|
1693
1803
|
/** Plugin-owned model-selection save endpoint (writes the settings section). */
|
|
1694
1804
|
export declare const POOL_MODELS_SAVE_PATH = "/plugins/dsh-workbuddy-xdpool/models/save";
|
|
1805
|
+
/**
|
|
1806
|
+
* Throw one account out of the pool for good, or take it back.
|
|
1807
|
+
*
|
|
1808
|
+
* Separate from the disable route because the semantics differ: disabling is a
|
|
1809
|
+
* rotation preference the account survives, ignoring survives the account.
|
|
1810
|
+
*/
|
|
1811
|
+
export declare const POOL_ACCOUNT_IGNORE_PATH = "/plugins/dsh-workbuddy-xdpool/accounts/ignored";
|
|
1695
1812
|
/** Run one automation job immediately, so the card can verify it on demand. */
|
|
1696
1813
|
export declare const POOL_AUTOMATION_RUN_PATH = "/plugins/dsh-workbuddy-xdpool/automation/run";
|
|
1697
1814
|
/** Set or clear one account's reserved-credit floor. */
|
|
1698
1815
|
export declare const POOL_CREDIT_RESERVE_PATH = "/plugins/dsh-workbuddy-xdpool/accounts/credit-reserve";
|
|
1699
|
-
/** One
|
|
1816
|
+
/** One account's row, token-free. */
|
|
1700
1817
|
interface PoolWebAccount {
|
|
1701
1818
|
id: string;
|
|
1702
1819
|
label: string;
|
|
@@ -1826,6 +1943,34 @@ interface PoolWebModel {
|
|
|
1826
1943
|
/** Whether this model is currently enabled in the picker. */
|
|
1827
1944
|
enabled: boolean;
|
|
1828
1945
|
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Body of the account ignore/unignore route: exactly one account per request.
|
|
1948
|
+
*
|
|
1949
|
+
* `ignored: true` throws the account out of the pool for good (its credential is
|
|
1950
|
+
* not even read on the next scan, and a fresh desktop sign-in will not bring it
|
|
1951
|
+
* back). `false` restores it, at which point the next scan discovers it again.
|
|
1952
|
+
*/
|
|
1953
|
+
interface PoolWebAccountIgnore {
|
|
1954
|
+
/** Pool account id, as reported in `PoolWebAccount.id`. */
|
|
1955
|
+
accountId: string;
|
|
1956
|
+
/** `true` ignores the account permanently; `false` takes it back. */
|
|
1957
|
+
ignored: boolean;
|
|
1958
|
+
}
|
|
1959
|
+
/**
|
|
1960
|
+
* One account the user has thrown out of the pool.
|
|
1961
|
+
*
|
|
1962
|
+
* Kept on the status document so the card can list what was ignored and offer a
|
|
1963
|
+
* way back: without that, "ignored" is a one-way door the user cannot inspect or
|
|
1964
|
+
* undo from the UI, which is how a hidden list becomes a support burden.
|
|
1965
|
+
*/
|
|
1966
|
+
interface PoolWebIgnoredAccount {
|
|
1967
|
+
/** Pool account id, the same key `PoolWebAccount.id` uses. */
|
|
1968
|
+
id: string;
|
|
1969
|
+
/** Human label captured at ignore time, so the row reads without a rescan. */
|
|
1970
|
+
label: string;
|
|
1971
|
+
/** ISO timestamp of when it was ignored. */
|
|
1972
|
+
ignoredAt: string;
|
|
1973
|
+
}
|
|
1829
1974
|
interface PoolWebModelSelection {
|
|
1830
1975
|
/** Absent = every model is enabled. */
|
|
1831
1976
|
enabledModelIds?: readonly string[];
|
|
@@ -1861,11 +2006,34 @@ interface PoolWebStatus {
|
|
|
1861
2006
|
automation: PoolWebAutomation;
|
|
1862
2007
|
/** Per-account credit floors currently in force, keyed by account id. */
|
|
1863
2008
|
creditReserves: Readonly<Record<string, number>>;
|
|
2009
|
+
/**
|
|
2010
|
+
* Accounts thrown out of the pool, in the order they were ignored.
|
|
2011
|
+
*
|
|
2012
|
+
* Reported so the card can show the list and offer a way back. These accounts
|
|
2013
|
+
* are NOT in `accounts`: they are filtered out before their credentials are
|
|
2014
|
+
* read, which is the whole point of the feature.
|
|
2015
|
+
*/
|
|
2016
|
+
ignored: readonly PoolWebIgnoredAccount[];
|
|
1864
2017
|
}
|
|
1865
2018
|
/** One automation job's last run, as shown on the card. */
|
|
1866
2019
|
interface PoolWebAutomationJob {
|
|
1867
2020
|
/** `YYYY-MM-DD` of the last run in this process, if it has run. */
|
|
1868
2021
|
lastRunDate?: string;
|
|
2022
|
+
/**
|
|
2023
|
+
* Epoch ms of the last run, so the card can show the TIME.
|
|
2024
|
+
*
|
|
2025
|
+
* Carried because a date-only stamp cannot tell one run from eight: every
|
|
2026
|
+
* repeat inside the same day rendered as the identical `2026-09-28 · 2`,
|
|
2027
|
+
* which is what kept a "re-runs every hour" defect invisible on the card.
|
|
2028
|
+
*/
|
|
2029
|
+
lastRunAtMs?: number;
|
|
2030
|
+
/**
|
|
2031
|
+
* Configured slots consumed today, as `YYYY-MM-DDTHH`.
|
|
2032
|
+
*
|
|
2033
|
+
* Shown so "which of today's hours already ran" is answerable at a glance
|
|
2034
|
+
* rather than inferred from a counter.
|
|
2035
|
+
*/
|
|
2036
|
+
firedSlots?: readonly string[];
|
|
1869
2037
|
/** Accounts that finished without error on the last run. */
|
|
1870
2038
|
ok: number;
|
|
1871
2039
|
/** Accounts that failed on the last run (each one skipped, the run continued). */
|
|
@@ -1952,6 +2120,89 @@ interface PoolWebAutomationEarnings {
|
|
|
1952
2120
|
type PoolRegion = 'cn' | 'global';
|
|
1953
2121
|
/** How the pool spreads requests across its accounts. */
|
|
1954
2122
|
type PoolDistribution = 'priority' | 'round-robin' | 'balanced';
|
|
2123
|
+
/**
|
|
2124
|
+
* The schedule every automation job falls back to.
|
|
2125
|
+
*
|
|
2126
|
+
* Shared by both halves on purpose. The host uses it when a configured hour
|
|
2127
|
+
* list arrives empty (the settings schema materializes "never configured" into
|
|
2128
|
+
* `[]`), and the card uses it when it writes the `automation` block back, so a
|
|
2129
|
+
* document that already holds an empty list is healed instead of being saved
|
|
2130
|
+
* back as an unrunnable schedule.
|
|
2131
|
+
*
|
|
2132
|
+
* This lives here rather than in `scheduler.ts` because the browser half cannot
|
|
2133
|
+
* import the host module: `scheduler.ts` pulls in `node:crypto` and the whole
|
|
2134
|
+
* upstream client, none of which exists in the browser bundle. Two hand-written
|
|
2135
|
+
* copies would drift, and the drift is invisible — the card would write a
|
|
2136
|
+
* schedule the scheduler does not run.
|
|
2137
|
+
*/
|
|
2138
|
+
export declare const DEFAULT_AUTOMATION_HOURS: {
|
|
2139
|
+
readonly checkin: readonly [9];
|
|
2140
|
+
readonly report: readonly [10];
|
|
2141
|
+
readonly tasks: readonly [11];
|
|
2142
|
+
readonly streak: readonly [12];
|
|
2143
|
+
readonly travel: readonly [9, 21];
|
|
2144
|
+
};
|
|
2145
|
+
//#endregion
|
|
2146
|
+
//#region src/ignored.d.ts
|
|
2147
|
+
/** Directory holding this plugin's own state (imported snapshots, ignore list). */
|
|
2148
|
+
export declare const PLUGIN_DATA_DIR_NAME = ".workbuddy-xdpool";
|
|
2149
|
+
/** File holding the permanent ignore list, inside {@link pluginDataDir}. */
|
|
2150
|
+
export declare const IGNORED_FILE_NAME = "ignored.json";
|
|
2151
|
+
/** One ignored account, as stored on disk and shown on the card. */
|
|
2152
|
+
type IgnoredAccount = PoolWebIgnoredAccount;
|
|
2153
|
+
/**
|
|
2154
|
+
* The DSH home directory, honouring the same override the host uses.
|
|
2155
|
+
*
|
|
2156
|
+
* Shared by the CLI and the host so both halves resolve the same file: an
|
|
2157
|
+
* `ignore` written from the terminal has to be visible to the running plugin,
|
|
2158
|
+
* which is only true if they agree on where "home" is.
|
|
2159
|
+
*/
|
|
2160
|
+
export declare function dshHome(env?: NodeJS.ProcessEnv): string;
|
|
2161
|
+
/** This plugin's own state directory. */
|
|
2162
|
+
export declare function pluginDataDir(env?: NodeJS.ProcessEnv): string;
|
|
2163
|
+
/** Absolute path of the ignore list. */
|
|
2164
|
+
export declare function ignoredIdsPath(env?: NodeJS.ProcessEnv): string;
|
|
2165
|
+
/**
|
|
2166
|
+
* Read the ignore list, tolerating every "no list yet" shape.
|
|
2167
|
+
*
|
|
2168
|
+
* A missing file, unreadable file, or invalid JSON all mean the same thing to
|
|
2169
|
+
* the caller — nothing is ignored — so none of them throws. The pool must be
|
|
2170
|
+
* able to start on a machine that has never ignored anything.
|
|
2171
|
+
*/
|
|
2172
|
+
export declare function readIgnoredAccounts(path?: string): Promise<IgnoredAccount[]>;
|
|
2173
|
+
/**
|
|
2174
|
+
* Synchronous read, for startup.
|
|
2175
|
+
*
|
|
2176
|
+
* The host applies the ignore list from inside `apply()`, which is synchronous,
|
|
2177
|
+
* and doing it there removes a startup race: an async load could resolve AFTER
|
|
2178
|
+
* the first account scan, which would let an ignored account slip into the pool
|
|
2179
|
+
* once per boot. The file is a few hundred bytes, so a blocking read at startup
|
|
2180
|
+
* costs nothing measurable.
|
|
2181
|
+
*/
|
|
2182
|
+
export declare function readIgnoredAccountsSync(path?: string): IgnoredAccount[];
|
|
2183
|
+
/**
|
|
2184
|
+
* Replace the ignore list, atomically.
|
|
2185
|
+
*
|
|
2186
|
+
* Written to a sibling temp file and renamed over the target so a crash (or a
|
|
2187
|
+
* concurrent reader) can never observe a half-written document — the ignore
|
|
2188
|
+
* list is the only thing standing between a dead account and the rotation, and
|
|
2189
|
+
* a truncated file reads as "nothing is ignored", which would quietly put every
|
|
2190
|
+
* discarded account back in the pool.
|
|
2191
|
+
*/
|
|
2192
|
+
export declare function writeIgnoredAccounts(accounts: readonly IgnoredAccount[], path?: string): Promise<void>;
|
|
2193
|
+
/**
|
|
2194
|
+
* Add one account to the ignore list, preserving the rest.
|
|
2195
|
+
*
|
|
2196
|
+
* A read-modify-write rather than a wholesale replace: the card and the CLI can
|
|
2197
|
+
* both be open, and each request names exactly one account, so re-writing the
|
|
2198
|
+
* whole list from a stale view would drop the other side's edits.
|
|
2199
|
+
*/
|
|
2200
|
+
export declare function ignoreAccount(account: {
|
|
2201
|
+
id: string;
|
|
2202
|
+
label?: string;
|
|
2203
|
+
}, path?: string): Promise<IgnoredAccount[]>;
|
|
2204
|
+
/** Drop one account from the ignore list. Returns the resulting list. */
|
|
2205
|
+
export declare function unignoreAccount(accountId: string, path?: string): Promise<IgnoredAccount[]>;
|
|
1955
2206
|
//#endregion
|
|
1956
2207
|
//#region src/web-status.d.ts
|
|
1957
2208
|
/** Constructor dependencies — a narrow slice of the pool runtime. */
|
|
@@ -2005,6 +2256,21 @@ interface PoolStatusRouteOptions {
|
|
|
2005
2256
|
* Absent without a settings service: the route then answers 503.
|
|
2006
2257
|
*/
|
|
2007
2258
|
setAccountDisabled?: (accountId: string, disabled: boolean) => Promise<void> | void;
|
|
2259
|
+
/**
|
|
2260
|
+
* Throw one account out of the pool for good, or take it back.
|
|
2261
|
+
*
|
|
2262
|
+
* Backed by the plugin's own ignore file rather than the settings document,
|
|
2263
|
+
* because the CLI writes the same list and has no settings service. Absent
|
|
2264
|
+
* when the host did not wire it: the route then answers 503.
|
|
2265
|
+
*/
|
|
2266
|
+
setAccountIgnored?: (accountId: string, ignored: boolean) => Promise<void> | void;
|
|
2267
|
+
/**
|
|
2268
|
+
* The accounts currently ignored, for the card's "ignored" list.
|
|
2269
|
+
*
|
|
2270
|
+
* A thunk rather than a snapshot so the document always reflects the file on
|
|
2271
|
+
* disk, including edits made by the CLI while the card is open.
|
|
2272
|
+
*/
|
|
2273
|
+
ignoredAccounts?: () => readonly PoolWebIgnoredAccount[];
|
|
2008
2274
|
}
|
|
2009
2275
|
/**
|
|
2010
2276
|
* Assemble the card's status document. Per-account credits and check-in state
|
|
@@ -2214,4 +2480,4 @@ export declare function createCore(logger?: {
|
|
|
2214
2480
|
*/
|
|
2215
2481
|
export declare function apply(ctx: Context, config?: Config): void;
|
|
2216
2482
|
//#endregion
|
|
2217
|
-
export type { AccountStatus, AutomationLedger, AutomationRunSummary, AutomationStatus, Context, ExpertUseMode, MarketExpert, ModelSelection, PoolStatusRouteOptions, PoolWebCheckin, PoolWebCheckinClaim, PoolWebModel, PoolWebModelSelection, PoolWebStatus, SchedulerLogger, TaskEventChain, TaskEventTransport, UpstreamErrorKind, WorkBuddyAccount, WorkBuddyAdapter, WorkBuddyCredential, WorkBuddyModelInfo, WorkBuddyShim, WorkBuddyStatus };
|
|
2483
|
+
export type { AccountStatus, AutomationLedger, AutomationRunSummary, AutomationStatus, Context, ExpertUseMode, IgnoredAccount, MarketExpert, ModelSelection, PoolStatusRouteOptions, PoolWebAccountIgnore, PoolWebCheckin, PoolWebCheckinClaim, PoolWebIgnoredAccount, PoolWebModel, PoolWebModelSelection, PoolWebStatus, SchedulerLogger, TaskEventChain, TaskEventTransport, UpstreamErrorKind, WorkBuddyAccount, WorkBuddyAdapter, WorkBuddyCredential, WorkBuddyModelInfo, WorkBuddyShim, WorkBuddyStatus };
|