dsh-workbuddy-xdpool 1.6.1 → 1.7.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 +285 -0
- package/lib/bin.js +441 -51
- package/lib/client.js +764 -425
- package/lib/index.d.ts +209 -4
- package/lib/index.js +571 -83
- package/package.json +3 -3
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 {
|
|
@@ -1413,7 +1469,7 @@ export declare class WorkBuddyScheduler {
|
|
|
1413
1469
|
* long before the settings section exists; a ledger written before that point
|
|
1414
1470
|
* would have nowhere to go.
|
|
1415
1471
|
*/
|
|
1416
|
-
setEarningsPersistence(save: (ledger: AutomationLedger) => void): void;
|
|
1472
|
+
setEarningsPersistence(save: (ledger: AutomationLedger) => void | Promise<void>): void;
|
|
1417
1473
|
/**
|
|
1418
1474
|
* Fold a previously persisted ledger back in, when it belongs to today.
|
|
1419
1475
|
*
|
|
@@ -1692,11 +1748,18 @@ export declare const POOL_RESET_COOLDOWN_PATH = "/plugins/dsh-workbuddy-xdpool/c
|
|
|
1692
1748
|
export declare const POOL_CHECKIN_PATH = "/plugins/dsh-workbuddy-xdpool/checkin";
|
|
1693
1749
|
/** Plugin-owned model-selection save endpoint (writes the settings section). */
|
|
1694
1750
|
export declare const POOL_MODELS_SAVE_PATH = "/plugins/dsh-workbuddy-xdpool/models/save";
|
|
1751
|
+
/**
|
|
1752
|
+
* Throw one account out of the pool for good, or take it back.
|
|
1753
|
+
*
|
|
1754
|
+
* Separate from the disable route because the semantics differ: disabling is a
|
|
1755
|
+
* rotation preference the account survives, ignoring survives the account.
|
|
1756
|
+
*/
|
|
1757
|
+
export declare const POOL_ACCOUNT_IGNORE_PATH = "/plugins/dsh-workbuddy-xdpool/accounts/ignored";
|
|
1695
1758
|
/** Run one automation job immediately, so the card can verify it on demand. */
|
|
1696
1759
|
export declare const POOL_AUTOMATION_RUN_PATH = "/plugins/dsh-workbuddy-xdpool/automation/run";
|
|
1697
1760
|
/** Set or clear one account's reserved-credit floor. */
|
|
1698
1761
|
export declare const POOL_CREDIT_RESERVE_PATH = "/plugins/dsh-workbuddy-xdpool/accounts/credit-reserve";
|
|
1699
|
-
/** One
|
|
1762
|
+
/** One account's row, token-free. */
|
|
1700
1763
|
interface PoolWebAccount {
|
|
1701
1764
|
id: string;
|
|
1702
1765
|
label: string;
|
|
@@ -1826,6 +1889,34 @@ interface PoolWebModel {
|
|
|
1826
1889
|
/** Whether this model is currently enabled in the picker. */
|
|
1827
1890
|
enabled: boolean;
|
|
1828
1891
|
}
|
|
1892
|
+
/**
|
|
1893
|
+
* Body of the account ignore/unignore route: exactly one account per request.
|
|
1894
|
+
*
|
|
1895
|
+
* `ignored: true` throws the account out of the pool for good (its credential is
|
|
1896
|
+
* not even read on the next scan, and a fresh desktop sign-in will not bring it
|
|
1897
|
+
* back). `false` restores it, at which point the next scan discovers it again.
|
|
1898
|
+
*/
|
|
1899
|
+
interface PoolWebAccountIgnore {
|
|
1900
|
+
/** Pool account id, as reported in `PoolWebAccount.id`. */
|
|
1901
|
+
accountId: string;
|
|
1902
|
+
/** `true` ignores the account permanently; `false` takes it back. */
|
|
1903
|
+
ignored: boolean;
|
|
1904
|
+
}
|
|
1905
|
+
/**
|
|
1906
|
+
* One account the user has thrown out of the pool.
|
|
1907
|
+
*
|
|
1908
|
+
* Kept on the status document so the card can list what was ignored and offer a
|
|
1909
|
+
* way back: without that, "ignored" is a one-way door the user cannot inspect or
|
|
1910
|
+
* undo from the UI, which is how a hidden list becomes a support burden.
|
|
1911
|
+
*/
|
|
1912
|
+
interface PoolWebIgnoredAccount {
|
|
1913
|
+
/** Pool account id, the same key `PoolWebAccount.id` uses. */
|
|
1914
|
+
id: string;
|
|
1915
|
+
/** Human label captured at ignore time, so the row reads without a rescan. */
|
|
1916
|
+
label: string;
|
|
1917
|
+
/** ISO timestamp of when it was ignored. */
|
|
1918
|
+
ignoredAt: string;
|
|
1919
|
+
}
|
|
1829
1920
|
interface PoolWebModelSelection {
|
|
1830
1921
|
/** Absent = every model is enabled. */
|
|
1831
1922
|
enabledModelIds?: readonly string[];
|
|
@@ -1861,6 +1952,14 @@ interface PoolWebStatus {
|
|
|
1861
1952
|
automation: PoolWebAutomation;
|
|
1862
1953
|
/** Per-account credit floors currently in force, keyed by account id. */
|
|
1863
1954
|
creditReserves: Readonly<Record<string, number>>;
|
|
1955
|
+
/**
|
|
1956
|
+
* Accounts thrown out of the pool, in the order they were ignored.
|
|
1957
|
+
*
|
|
1958
|
+
* Reported so the card can show the list and offer a way back. These accounts
|
|
1959
|
+
* are NOT in `accounts`: they are filtered out before their credentials are
|
|
1960
|
+
* read, which is the whole point of the feature.
|
|
1961
|
+
*/
|
|
1962
|
+
ignored: readonly PoolWebIgnoredAccount[];
|
|
1864
1963
|
}
|
|
1865
1964
|
/** One automation job's last run, as shown on the card. */
|
|
1866
1965
|
interface PoolWebAutomationJob {
|
|
@@ -1952,6 +2051,89 @@ interface PoolWebAutomationEarnings {
|
|
|
1952
2051
|
type PoolRegion = 'cn' | 'global';
|
|
1953
2052
|
/** How the pool spreads requests across its accounts. */
|
|
1954
2053
|
type PoolDistribution = 'priority' | 'round-robin' | 'balanced';
|
|
2054
|
+
/**
|
|
2055
|
+
* The schedule every automation job falls back to.
|
|
2056
|
+
*
|
|
2057
|
+
* Shared by both halves on purpose. The host uses it when a configured hour
|
|
2058
|
+
* list arrives empty (the settings schema materializes "never configured" into
|
|
2059
|
+
* `[]`), and the card uses it when it writes the `automation` block back, so a
|
|
2060
|
+
* document that already holds an empty list is healed instead of being saved
|
|
2061
|
+
* back as an unrunnable schedule.
|
|
2062
|
+
*
|
|
2063
|
+
* This lives here rather than in `scheduler.ts` because the browser half cannot
|
|
2064
|
+
* import the host module: `scheduler.ts` pulls in `node:crypto` and the whole
|
|
2065
|
+
* upstream client, none of which exists in the browser bundle. Two hand-written
|
|
2066
|
+
* copies would drift, and the drift is invisible — the card would write a
|
|
2067
|
+
* schedule the scheduler does not run.
|
|
2068
|
+
*/
|
|
2069
|
+
export declare const DEFAULT_AUTOMATION_HOURS: {
|
|
2070
|
+
readonly checkin: readonly [9];
|
|
2071
|
+
readonly report: readonly [10];
|
|
2072
|
+
readonly tasks: readonly [11];
|
|
2073
|
+
readonly streak: readonly [12];
|
|
2074
|
+
readonly travel: readonly [9, 21];
|
|
2075
|
+
};
|
|
2076
|
+
//#endregion
|
|
2077
|
+
//#region src/ignored.d.ts
|
|
2078
|
+
/** Directory holding this plugin's own state (imported snapshots, ignore list). */
|
|
2079
|
+
export declare const PLUGIN_DATA_DIR_NAME = ".workbuddy-xdpool";
|
|
2080
|
+
/** File holding the permanent ignore list, inside {@link pluginDataDir}. */
|
|
2081
|
+
export declare const IGNORED_FILE_NAME = "ignored.json";
|
|
2082
|
+
/** One ignored account, as stored on disk and shown on the card. */
|
|
2083
|
+
type IgnoredAccount = PoolWebIgnoredAccount;
|
|
2084
|
+
/**
|
|
2085
|
+
* The DSH home directory, honouring the same override the host uses.
|
|
2086
|
+
*
|
|
2087
|
+
* Shared by the CLI and the host so both halves resolve the same file: an
|
|
2088
|
+
* `ignore` written from the terminal has to be visible to the running plugin,
|
|
2089
|
+
* which is only true if they agree on where "home" is.
|
|
2090
|
+
*/
|
|
2091
|
+
export declare function dshHome(env?: NodeJS.ProcessEnv): string;
|
|
2092
|
+
/** This plugin's own state directory. */
|
|
2093
|
+
export declare function pluginDataDir(env?: NodeJS.ProcessEnv): string;
|
|
2094
|
+
/** Absolute path of the ignore list. */
|
|
2095
|
+
export declare function ignoredIdsPath(env?: NodeJS.ProcessEnv): string;
|
|
2096
|
+
/**
|
|
2097
|
+
* Read the ignore list, tolerating every "no list yet" shape.
|
|
2098
|
+
*
|
|
2099
|
+
* A missing file, unreadable file, or invalid JSON all mean the same thing to
|
|
2100
|
+
* the caller — nothing is ignored — so none of them throws. The pool must be
|
|
2101
|
+
* able to start on a machine that has never ignored anything.
|
|
2102
|
+
*/
|
|
2103
|
+
export declare function readIgnoredAccounts(path?: string): Promise<IgnoredAccount[]>;
|
|
2104
|
+
/**
|
|
2105
|
+
* Synchronous read, for startup.
|
|
2106
|
+
*
|
|
2107
|
+
* The host applies the ignore list from inside `apply()`, which is synchronous,
|
|
2108
|
+
* and doing it there removes a startup race: an async load could resolve AFTER
|
|
2109
|
+
* the first account scan, which would let an ignored account slip into the pool
|
|
2110
|
+
* once per boot. The file is a few hundred bytes, so a blocking read at startup
|
|
2111
|
+
* costs nothing measurable.
|
|
2112
|
+
*/
|
|
2113
|
+
export declare function readIgnoredAccountsSync(path?: string): IgnoredAccount[];
|
|
2114
|
+
/**
|
|
2115
|
+
* Replace the ignore list, atomically.
|
|
2116
|
+
*
|
|
2117
|
+
* Written to a sibling temp file and renamed over the target so a crash (or a
|
|
2118
|
+
* concurrent reader) can never observe a half-written document — the ignore
|
|
2119
|
+
* list is the only thing standing between a dead account and the rotation, and
|
|
2120
|
+
* a truncated file reads as "nothing is ignored", which would quietly put every
|
|
2121
|
+
* discarded account back in the pool.
|
|
2122
|
+
*/
|
|
2123
|
+
export declare function writeIgnoredAccounts(accounts: readonly IgnoredAccount[], path?: string): Promise<void>;
|
|
2124
|
+
/**
|
|
2125
|
+
* Add one account to the ignore list, preserving the rest.
|
|
2126
|
+
*
|
|
2127
|
+
* A read-modify-write rather than a wholesale replace: the card and the CLI can
|
|
2128
|
+
* both be open, and each request names exactly one account, so re-writing the
|
|
2129
|
+
* whole list from a stale view would drop the other side's edits.
|
|
2130
|
+
*/
|
|
2131
|
+
export declare function ignoreAccount(account: {
|
|
2132
|
+
id: string;
|
|
2133
|
+
label?: string;
|
|
2134
|
+
}, path?: string): Promise<IgnoredAccount[]>;
|
|
2135
|
+
/** Drop one account from the ignore list. Returns the resulting list. */
|
|
2136
|
+
export declare function unignoreAccount(accountId: string, path?: string): Promise<IgnoredAccount[]>;
|
|
1955
2137
|
//#endregion
|
|
1956
2138
|
//#region src/web-status.d.ts
|
|
1957
2139
|
/** Constructor dependencies — a narrow slice of the pool runtime. */
|
|
@@ -2005,6 +2187,21 @@ interface PoolStatusRouteOptions {
|
|
|
2005
2187
|
* Absent without a settings service: the route then answers 503.
|
|
2006
2188
|
*/
|
|
2007
2189
|
setAccountDisabled?: (accountId: string, disabled: boolean) => Promise<void> | void;
|
|
2190
|
+
/**
|
|
2191
|
+
* Throw one account out of the pool for good, or take it back.
|
|
2192
|
+
*
|
|
2193
|
+
* Backed by the plugin's own ignore file rather than the settings document,
|
|
2194
|
+
* because the CLI writes the same list and has no settings service. Absent
|
|
2195
|
+
* when the host did not wire it: the route then answers 503.
|
|
2196
|
+
*/
|
|
2197
|
+
setAccountIgnored?: (accountId: string, ignored: boolean) => Promise<void> | void;
|
|
2198
|
+
/**
|
|
2199
|
+
* The accounts currently ignored, for the card's "ignored" list.
|
|
2200
|
+
*
|
|
2201
|
+
* A thunk rather than a snapshot so the document always reflects the file on
|
|
2202
|
+
* disk, including edits made by the CLI while the card is open.
|
|
2203
|
+
*/
|
|
2204
|
+
ignoredAccounts?: () => readonly PoolWebIgnoredAccount[];
|
|
2008
2205
|
}
|
|
2009
2206
|
/**
|
|
2010
2207
|
* Assemble the card's status document. Per-account credits and check-in state
|
|
@@ -2158,6 +2355,14 @@ export declare const modelSelectionKeyFor: (region: 'cn' | 'global') => string;
|
|
|
2158
2355
|
* also why `contextBudgets` is a real dictionary (`z.dict`) - an open object
|
|
2159
2356
|
* schema reads as "an object with no fields" and the fold then throws while
|
|
2160
2357
|
* the provider row is rendered.
|
|
2358
|
+
*
|
|
2359
|
+
* Every field is wrapped in {@link asVolatile}: on the 0.1.7 line the settings
|
|
2360
|
+
* write gate refuses an entry whose schema declares no volatile field at all
|
|
2361
|
+
* ("Plugin entry ... has no volatile fields") and `describe()` skips such an
|
|
2362
|
+
* entry — so an unmarked schema means the card can neither render nor save. On
|
|
2363
|
+
* the 0.1.5 line the wrapper degrades to an identity no-op (see its JSDoc), and
|
|
2364
|
+
* the value the running instance reads is a plain value either way once
|
|
2365
|
+
* unwrapped.
|
|
2161
2366
|
*/
|
|
2162
2367
|
export declare const Config: z<Config>;
|
|
2163
2368
|
/** Everything the CLI needs from a live plugin instance. */
|
|
@@ -2206,4 +2411,4 @@ export declare function createCore(logger?: {
|
|
|
2206
2411
|
*/
|
|
2207
2412
|
export declare function apply(ctx: Context, config?: Config): void;
|
|
2208
2413
|
//#endregion
|
|
2209
|
-
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 };
|
|
2414
|
+
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 };
|