dsh-xdpool 2.5.1 → 2.6.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 +169 -0
- package/README.en.md +10 -5
- package/README.md +10 -5
- package/assets/community-qr-qq.jpg +0 -0
- package/assets/community-qr-wechat.jpg +0 -0
- package/lib/bin.js +427 -74
- package/lib/client.js +1060 -235
- package/lib/index.d.ts +376 -61
- package/lib/index.js +2097 -937
- package/package.json +1 -1
- package/vendor/channel-pack/pack.js +346 -24
- package/assets/community-qr.png +0 -0
package/lib/index.d.ts
CHANGED
|
@@ -1066,6 +1066,16 @@ export declare class WorkBuddyAccountPool {
|
|
|
1066
1066
|
* lives on the pool and is re-applied from settings after each scan.
|
|
1067
1067
|
*/
|
|
1068
1068
|
private disabledIds;
|
|
1069
|
+
/**
|
|
1070
|
+
* The account ids the store held after the last successful write.
|
|
1071
|
+
*
|
|
1072
|
+
* Read back on the next scan to say WHICH accounts left, not just how many.
|
|
1073
|
+
* The list is written wholesale, so a scan that does not find an account
|
|
1074
|
+
* deletes it — and that account's credential is then unrecoverable without a
|
|
1075
|
+
* fresh sign-in (#117). `undefined` until the first write, so the first scan
|
|
1076
|
+
* never reports every account as "leave".
|
|
1077
|
+
*/
|
|
1078
|
+
private lastPersistedIds;
|
|
1069
1079
|
/**
|
|
1070
1080
|
* Account ids the user threw out of the pool for good.
|
|
1071
1081
|
*
|
|
@@ -1143,6 +1153,11 @@ export declare class WorkBuddyAccountPool {
|
|
|
1143
1153
|
* A function rather than a list because that pool is mounted asynchronously
|
|
1144
1154
|
* and can be re-read on demand; `undefined` means "no such source", which is
|
|
1145
1155
|
* the state every test and every pre-mount startup is in.
|
|
1156
|
+
*
|
|
1157
|
+
* The `| undefined` is explicit because `applyExternalSource` CLEARS the field by
|
|
1158
|
+
* assigning `undefined` — under `exactOptionalPropertyTypes` a bare `?:` means
|
|
1159
|
+
* "may be absent, never undefined", which made that documented clearing action
|
|
1160
|
+
* a type error.
|
|
1146
1161
|
*/
|
|
1147
1162
|
private externalSource?;
|
|
1148
1163
|
constructor(options?: AccountPoolOptions);
|
|
@@ -1414,6 +1429,28 @@ export declare class WorkBuddyAccountPool {
|
|
|
1414
1429
|
clearCredentialDead(accountId: string): void;
|
|
1415
1430
|
/** Accounts currently kept out of rotation because their sign-in was rejected. */
|
|
1416
1431
|
deadCredentials(): readonly WorkBuddyAccount[];
|
|
1432
|
+
/**
|
|
1433
|
+
* Try to bring benched accounts back WITHOUT waiting out the cooldown.
|
|
1434
|
+
*
|
|
1435
|
+
* The cooldown is a guess about how long a problem lasts, and the guess is
|
|
1436
|
+
* usually wrong in one direction or the other: a token revoked by a password
|
|
1437
|
+
* change stays dead for the full window even after the user signs in again in
|
|
1438
|
+
* some other client, and a transient upstream hiccup benches a perfectly good
|
|
1439
|
+
* account for half an hour.
|
|
1440
|
+
*
|
|
1441
|
+
* So instead of only waiting, ask. For each benched account, one cheap
|
|
1442
|
+
* authenticated read: if it answers, the credential works and the account goes
|
|
1443
|
+
* back into rotation immediately. Nothing about the failure is trusted — only a
|
|
1444
|
+
* successful call clears it — and a probe that fails keeps the original
|
|
1445
|
+
* cooldown untouched (probing must never EXTEND a bench, or a broken endpoint
|
|
1446
|
+
* would keep every account locked out for as long as it stayed broken).
|
|
1447
|
+
*
|
|
1448
|
+
* `probe` is injected rather than imported so this class stays free of the
|
|
1449
|
+
* upstream client: the pool knows about accounts, not about HTTP.
|
|
1450
|
+
*
|
|
1451
|
+
* Returns the accounts it revived, for logging and for the run summary.
|
|
1452
|
+
*/
|
|
1453
|
+
reviveBenched(probe: (credential: WorkBuddyCredential) => Promise<unknown>): Promise<readonly WorkBuddyAccount[]>;
|
|
1417
1454
|
/**
|
|
1418
1455
|
* Refresh the account's access token when it is within the margin (or already
|
|
1419
1456
|
* expired), in-flight de-duped per account. A failed refresh keeps the
|
|
@@ -1517,6 +1554,35 @@ type PoolWebAggregatePatch = {
|
|
|
1517
1554
|
providerId: string;
|
|
1518
1555
|
enabled?: boolean;
|
|
1519
1556
|
apiKey?: string;
|
|
1557
|
+
/**
|
|
1558
|
+
* Every key, preferred first — replaces whatever was stored.
|
|
1559
|
+
*
|
|
1560
|
+
* A REPLACEMENT rather than a delta, for the same reason `models` is: the
|
|
1561
|
+
* card sends the whole list it is showing, and a delta would let two open
|
|
1562
|
+
* tabs interleave into a set neither of them chose. An empty array clears
|
|
1563
|
+
* every key.
|
|
1564
|
+
*/
|
|
1565
|
+
apiKeys?: readonly string[];
|
|
1566
|
+
/**
|
|
1567
|
+
* Append ONE key to the stored list.
|
|
1568
|
+
*
|
|
1569
|
+
* The card cannot send `apiKeys`, because the read route never echoes keys
|
|
1570
|
+
* back — it reports only `keyCount`. A replacement list from the browser
|
|
1571
|
+
* would therefore have to be built from placeholders, and would overwrite
|
|
1572
|
+
* every key the user cannot see. This field says "add this one after the
|
|
1573
|
+
* ones already stored", which is the only instruction the card can honestly
|
|
1574
|
+
* give.
|
|
1575
|
+
*
|
|
1576
|
+
* Ignored when it duplicates a stored key.
|
|
1577
|
+
*/
|
|
1578
|
+
appendApiKey?: string;
|
|
1579
|
+
/**
|
|
1580
|
+
* How requests spread across those keys.
|
|
1581
|
+
*
|
|
1582
|
+
* Same vocabulary as the pool lane (`priority`, `round-robin`, `balanced`,
|
|
1583
|
+
* `sticky`, `expiry`); unknown values are rejected rather than stored.
|
|
1584
|
+
*/
|
|
1585
|
+
distribution?: string;
|
|
1520
1586
|
baseUrl?: string;
|
|
1521
1587
|
/**
|
|
1522
1588
|
* The chosen model set, replacing whatever this provider exposed before.
|
|
@@ -1589,6 +1655,23 @@ interface PoolWebAggregateProvider {
|
|
|
1589
1655
|
discovered: boolean;
|
|
1590
1656
|
/** When the provider was first configured. */
|
|
1591
1657
|
addedAt?: string;
|
|
1658
|
+
/**
|
|
1659
|
+
* How many keys this vendor holds.
|
|
1660
|
+
*
|
|
1661
|
+
* `0` for a keyless vendor, `1` for the ordinary case, more when the user
|
|
1662
|
+
* pasted alternates. The card needs the COUNT rather than the keys themselves —
|
|
1663
|
+
* keys never leave the host — because "account usage" only means anything when
|
|
1664
|
+
* there is something to distribute over: with one key it would be a switch with
|
|
1665
|
+
* a single option and no effect, so the card hides it.
|
|
1666
|
+
*/
|
|
1667
|
+
keyCount: number;
|
|
1668
|
+
/**
|
|
1669
|
+
* The usage strategy in force, when the user has chosen one.
|
|
1670
|
+
*
|
|
1671
|
+
* Absent means the documented default (priority). Shares the pool lane's
|
|
1672
|
+
* vocabulary so both kinds of card present one idea one way.
|
|
1673
|
+
*/
|
|
1674
|
+
distribution?: string;
|
|
1592
1675
|
}
|
|
1593
1676
|
/** The document {@link POOL_AGGREGATE_PATH} answers with. */
|
|
1594
1677
|
interface PoolWebAggregateStatus {
|
|
@@ -1687,6 +1770,19 @@ interface PoolWebComboCandidate {
|
|
|
1687
1770
|
usable: boolean;
|
|
1688
1771
|
contextWindow: number;
|
|
1689
1772
|
supportsImages: boolean;
|
|
1773
|
+
/**
|
|
1774
|
+
* Other lanes that serve the SAME model, best-first, excluding this row.
|
|
1775
|
+
*
|
|
1776
|
+
* The "same model, different route" tier: when one provider rate-limits, the
|
|
1777
|
+
* right move is usually to reach the same model through another provider, not
|
|
1778
|
+
* to fall back to a different model — a different model changes the context
|
|
1779
|
+
* window, tool-calling behaviour and writing style.
|
|
1780
|
+
*
|
|
1781
|
+
* Present so the card can offer "also try this model via …" in one click
|
|
1782
|
+
* instead of making the user find the same name under another vendor and add
|
|
1783
|
+
* it three times. Empty when the model has only one route.
|
|
1784
|
+
*/
|
|
1785
|
+
siblings: readonly string[];
|
|
1690
1786
|
}
|
|
1691
1787
|
/** One chain, resolved against the live roster. */
|
|
1692
1788
|
interface PoolWebCombo {
|
|
@@ -1695,6 +1791,21 @@ interface PoolWebCombo {
|
|
|
1695
1791
|
name: string;
|
|
1696
1792
|
/** Members that exist right now, in order. Empty means the chain is dead. */
|
|
1697
1793
|
models: readonly string[];
|
|
1794
|
+
/**
|
|
1795
|
+
* The chain as PLATFORM GROUPS, for the two-level editor.
|
|
1796
|
+
*
|
|
1797
|
+
* Always present — grouping `models` when the chain was saved flat — so the
|
|
1798
|
+
* editor never has to branch on which shape reached it. `models` stays the flat,
|
|
1799
|
+
* authoritative sequence; this is the same content arranged the way the router
|
|
1800
|
+
* walks it (platform order, then model order within each platform).
|
|
1801
|
+
*
|
|
1802
|
+
* Model ids here are BARE (no `provider/` prefix): the owner is the field beside
|
|
1803
|
+
* them, and carrying the prefix in both invites the two to disagree.
|
|
1804
|
+
*/
|
|
1805
|
+
platforms: readonly {
|
|
1806
|
+
owner: string;
|
|
1807
|
+
models: readonly string[];
|
|
1808
|
+
}[];
|
|
1698
1809
|
/** Members the user configured but which the roster no longer serves. */
|
|
1699
1810
|
missing: readonly string[];
|
|
1700
1811
|
strategy: 'fallback' | 'round-robin';
|
|
@@ -2137,9 +2248,40 @@ interface PoolWebAutomationJob {
|
|
|
2137
2248
|
* what turns a row from "it ran" into "it did the things I care about".
|
|
2138
2249
|
*/
|
|
2139
2250
|
detail?: readonly string[];
|
|
2251
|
+
/**
|
|
2252
|
+
* Per-item outcome of the last run, one entry per thing the job looked at.
|
|
2253
|
+
*
|
|
2254
|
+
* `detail` is free text and mixes counters with titles ("签到 +12",
|
|
2255
|
+
* "复活 Account A"), so the card can print it but cannot GROUP it. This is the
|
|
2256
|
+
* same information with a status attached, which is what makes "which tasks
|
|
2257
|
+
* are still unclaimed, and why" answerable:
|
|
2258
|
+
*
|
|
2259
|
+
* claimed — the reward was collected on this run
|
|
2260
|
+
* already — collected earlier today; nothing to do
|
|
2261
|
+
* skipped — the board would not let it be claimed (locked, no energy, …)
|
|
2262
|
+
* failed — the call came back an error
|
|
2263
|
+
*
|
|
2264
|
+
* Without it, "0 claimed" reads the same whether everything was already done,
|
|
2265
|
+
* the account had no energy, or the endpoint is broken — three situations with
|
|
2266
|
+
* three different fixes.
|
|
2267
|
+
*/
|
|
2268
|
+
items?: readonly PoolWebAutomationItem[];
|
|
2140
2269
|
/** A pending milestone worth naming, e.g. the next streak tier countdown. */
|
|
2141
2270
|
progress?: string;
|
|
2142
2271
|
}
|
|
2272
|
+
/** How one item of an automation run ended. */
|
|
2273
|
+
type PoolWebAutomationItemStatus = 'claimed' | 'already' | 'skipped' | 'failed';
|
|
2274
|
+
/** One item an automation job considered, with what happened to it. */
|
|
2275
|
+
interface PoolWebAutomationItem {
|
|
2276
|
+
/** The task board's own title, or a short label for a non-task step. */
|
|
2277
|
+
title: string;
|
|
2278
|
+
status: PoolWebAutomationItemStatus;
|
|
2279
|
+
/** Credits/energy collected, when the upstream reported any. */
|
|
2280
|
+
credit?: number;
|
|
2281
|
+
energy?: number;
|
|
2282
|
+
/** Why it was skipped or how it failed, in the upstream's words. */
|
|
2283
|
+
note?: string;
|
|
2284
|
+
}
|
|
2143
2285
|
/**
|
|
2144
2286
|
* Automation block on the status document.
|
|
2145
2287
|
*
|
|
@@ -2264,8 +2406,23 @@ interface WorkBuddyModelInfo {
|
|
|
2264
2406
|
* (`kimi-k3-1`). A stale fallback is worse than a short one — it looks
|
|
2265
2407
|
* authoritative while being wrong.
|
|
2266
2408
|
*
|
|
2267
|
-
*
|
|
2268
|
-
*
|
|
2409
|
+
* NO PRICES AND NO PROMO BADGES HERE. This table is what the picker shows when
|
|
2410
|
+
* the startup fetch fails, and a multiplier captured months ago is a price the
|
|
2411
|
+
* user will budget against while it is quietly wrong. Two specific harms:
|
|
2412
|
+
*
|
|
2413
|
+
* - `multiplier: 0` renders the "free" badge, so a model that was free at
|
|
2414
|
+
* capture time keeps claiming to be free after the promotion ends;
|
|
2415
|
+
* - a non-zero multiplier renders next to the model, so a stale figure reads
|
|
2416
|
+
* as the current rate.
|
|
2417
|
+
*
|
|
2418
|
+
* `undefined` is the honest state: the card prints no rate and no badge, which
|
|
2419
|
+
* is exactly true — this build does not know the price. The live fetch fills
|
|
2420
|
+
* both in within a second of a working startup, and `catalogSource` already
|
|
2421
|
+
* tells the card to say the list is the built-in one.
|
|
2422
|
+
*
|
|
2423
|
+
* Windows, output ceilings and the `craft` capability tag stay: those are
|
|
2424
|
+
* properties of the model, not of a campaign, and they are what makes the list
|
|
2425
|
+
* usable offline at all.
|
|
2269
2426
|
*/
|
|
2270
2427
|
export declare const FALLBACK_WORKBUDDY_MODELS: readonly WorkBuddyModelInfo[];
|
|
2271
2428
|
/** Which gateway a catalog describes. Mirrors `WorkBuddyRegion` in `upstream.ts`. */
|
|
@@ -2302,11 +2459,24 @@ export declare class WorkBuddyCatalog {
|
|
|
2302
2459
|
current(): readonly WorkBuddyModelInfo[];
|
|
2303
2460
|
/**
|
|
2304
2461
|
* The models DSH should actually offer, after applying the user's selection:
|
|
2305
|
-
* disabled models are dropped, an explicit image list
|
|
2306
|
-
*
|
|
2462
|
+
* disabled models are dropped, an explicit image list decides image support,
|
|
2463
|
+
* and a per-model budget caps the advertised window.
|
|
2307
2464
|
*
|
|
2308
2465
|
* An absent `enabledModelIds` means "everything" — a fresh install with no
|
|
2309
2466
|
* saved selection must not present an empty picker.
|
|
2467
|
+
*
|
|
2468
|
+
* IMAGE SUPPORT IS THE USER'S SET, NOT AN OR. The upstream flag is `true` for
|
|
2469
|
+
* essentially every model of this vendor (measured: 15 of 16 on CN, 23 of 23
|
|
2470
|
+
* on international), so `supportsImages || imageSet.has(id)` could only ever
|
|
2471
|
+
* turn the flag ON — un-ticking the box in the card changed nothing, and the
|
|
2472
|
+
* adapter kept advertising `['text','image']`. The checkbox existed and did
|
|
2473
|
+
* not work, which is worse than not offering it.
|
|
2474
|
+
*
|
|
2475
|
+
* So when the user HAS saved an image selection, that set is the answer, in
|
|
2476
|
+
* both directions. When they have not (undefined — a fresh install, or a
|
|
2477
|
+
* config written before this fix), the upstream capability stands: silently
|
|
2478
|
+
* disabling image input for everyone who never touched the switch would be a
|
|
2479
|
+
* regression, and the absent case is exactly "no opinion".
|
|
2310
2480
|
*/
|
|
2311
2481
|
visible(): readonly WorkBuddyModelInfo[];
|
|
2312
2482
|
/** Replace the catalog and notify the adapter to rebuild its model list. */
|
|
@@ -2373,7 +2543,42 @@ interface ProviderSetting {
|
|
|
2373
2543
|
* one vendor that WAS configured indistinguishable from the rest.
|
|
2374
2544
|
*/
|
|
2375
2545
|
enabled?: boolean;
|
|
2546
|
+
/**
|
|
2547
|
+
* The FIRST usable key, kept as the single-key spelling.
|
|
2548
|
+
*
|
|
2549
|
+
* Almost every provider needs one key, and a user pasting one must not have to
|
|
2550
|
+
* learn an array to do it. This field and {@link apiKeys} are kept in step by
|
|
2551
|
+
* `updateProviderSetting`: writing `apiKey` sets a one-entry list, and writing
|
|
2552
|
+
* `apiKeys` mirrors its first entry back here. Readers therefore do not have to
|
|
2553
|
+
* know which spelling a config file happens to hold.
|
|
2554
|
+
*/
|
|
2376
2555
|
apiKey?: string;
|
|
2556
|
+
/**
|
|
2557
|
+
* Every key this provider may rotate through.
|
|
2558
|
+
*
|
|
2559
|
+
* The pool has always rotated accounts, but a third-party vendor could only
|
|
2560
|
+
* ever hold ONE key, so "account usage" (priority / round-robin / balanced …)
|
|
2561
|
+
* had nothing to distribute over and was not offered on those cards. A vendor
|
|
2562
|
+
* with several keys on one account — which is how most rate limits are actually
|
|
2563
|
+
* dodged — could not express that at all.
|
|
2564
|
+
*
|
|
2565
|
+
* The first entry is the preferred one; the rest are alternates in order.
|
|
2566
|
+
* Absent or empty means "no key configured", which is the same state `apiKey`
|
|
2567
|
+
* has always described.
|
|
2568
|
+
*/
|
|
2569
|
+
apiKeys?: readonly string[];
|
|
2570
|
+
/**
|
|
2571
|
+
* How requests spread across those keys.
|
|
2572
|
+
*
|
|
2573
|
+
* The same five strategies the pool lane offers, and deliberately the same
|
|
2574
|
+
* vocabulary rather than a second set of names for one idea. Absent means
|
|
2575
|
+
* `priority`: use the preferred key until the vendor refuses it, then move on.
|
|
2576
|
+
*
|
|
2577
|
+
* Only meaningful when {@link apiKeys} holds more than one entry — with a single
|
|
2578
|
+
* key there is nothing to distribute over, which is why the card hides the row
|
|
2579
|
+
* in that case.
|
|
2580
|
+
*/
|
|
2581
|
+
distribution?: string;
|
|
2377
2582
|
/** User override for the base URL, for providers whose host is per-deployment. */
|
|
2378
2583
|
baseUrl?: string;
|
|
2379
2584
|
/**
|
|
@@ -2410,13 +2615,45 @@ interface AggregateSettings {
|
|
|
2410
2615
|
/** Chain strategies. Anything else on disk falls back to `fallback`. */
|
|
2411
2616
|
declare const COMBO_STRATEGIES: readonly ['fallback', 'round-robin'];
|
|
2412
2617
|
type ComboStrategy = (typeof COMBO_STRATEGIES)[number];
|
|
2618
|
+
/**
|
|
2619
|
+
* One platform's contribution to a chain: which lane, and which of its models.
|
|
2620
|
+
*
|
|
2621
|
+
* Chains are edited as a TWO-LEVEL list — platform order, then model order inside
|
|
2622
|
+
* each platform — because that is the order the router actually walks and the
|
|
2623
|
+
* order a reader thinks in ("try the bytes one, then Qoder; if both fail, go to
|
|
2624
|
+
* CodeBuddy"). A flat member list expresses the same sequence but cannot show the
|
|
2625
|
+
* grouping, so re-ordering "all of WorkBuddy's models together" meant moving them
|
|
2626
|
+
* one at a time and hoping none was missed.
|
|
2627
|
+
*
|
|
2628
|
+
* `owner` is `workbuddy` for a pool model, or an aggregate provider id. Model ids
|
|
2629
|
+
* are BARE here (no `provider/` prefix): the prefix is derived from the owner when
|
|
2630
|
+
* the chain is flattened, so storing it twice would let the two disagree.
|
|
2631
|
+
*/
|
|
2632
|
+
interface ComboPlatform {
|
|
2633
|
+
owner: string;
|
|
2634
|
+
models: readonly string[];
|
|
2635
|
+
}
|
|
2413
2636
|
/** A chain as the user configured it, before the catalogs are consulted. */
|
|
2414
2637
|
interface ComboSetting {
|
|
2415
2638
|
/** `combo:<slug>`; derived from the name when absent or malformed. */
|
|
2416
2639
|
id?: string;
|
|
2417
2640
|
name: string;
|
|
2418
|
-
/**
|
|
2641
|
+
/**
|
|
2642
|
+
* Member model ids in the order the user put them — the FLATTENED, authoritative
|
|
2643
|
+
* sequence the router walks.
|
|
2644
|
+
*
|
|
2645
|
+
* Kept as the single source of truth so every resolver, the picker row and the
|
|
2646
|
+
* shim keep reading one field. A chain saved with `platforms` also carries this,
|
|
2647
|
+
* derived from them, so an older build and an older config file both keep working.
|
|
2648
|
+
*/
|
|
2419
2649
|
models: readonly string[];
|
|
2650
|
+
/**
|
|
2651
|
+
* The same chain as platform groups, when it was edited that way.
|
|
2652
|
+
*
|
|
2653
|
+
* Absent for a chain written before this existed, or saved flat. The editor
|
|
2654
|
+
* groups such a chain by owner on the fly, so it opens correctly either way.
|
|
2655
|
+
*/
|
|
2656
|
+
platforms?: readonly ComboPlatform[];
|
|
2420
2657
|
/** How the chain advances; `fallback` restarts from the top each turn. */
|
|
2421
2658
|
strategy?: ComboStrategy;
|
|
2422
2659
|
/** Consecutive turns one member serves before `round-robin` advances. */
|
|
@@ -2493,60 +2730,6 @@ interface RelaySetting {
|
|
|
2493
2730
|
models?: string[];
|
|
2494
2731
|
}
|
|
2495
2732
|
//#endregion
|
|
2496
|
-
//#region src/aggregate.d.ts
|
|
2497
|
-
/** Registry `format` → the wire vocabulary this module speaks. */
|
|
2498
|
-
type AggregateWire = 'chat' | 'responses' | 'messages';
|
|
2499
|
-
/** One model the aggregate lane offers. */
|
|
2500
|
-
interface AggregateModelRow {
|
|
2501
|
-
/** Composite id: `providerId/modelId`, which is also the picker id. */
|
|
2502
|
-
id: string;
|
|
2503
|
-
/** Display name: the provider's own name plus the row's label. */
|
|
2504
|
-
name: string;
|
|
2505
|
-
providerId: string;
|
|
2506
|
-
modelId: string;
|
|
2507
|
-
contextWindow: number;
|
|
2508
|
-
maxOutputTokens: number;
|
|
2509
|
-
supportsImages: boolean;
|
|
2510
|
-
wire: AggregateWire;
|
|
2511
|
-
/** `static` from the registry, `discovered` from a live listing. */
|
|
2512
|
-
source: 'static' | 'discovered';
|
|
2513
|
-
}
|
|
2514
|
-
/** One stored aggregate row set, refreshed on change, for the shim and adapter. */
|
|
2515
|
-
declare class AggregateCatalog {
|
|
2516
|
-
private readonly read;
|
|
2517
|
-
private readonly poolRows;
|
|
2518
|
-
private rows;
|
|
2519
|
-
private chainRows;
|
|
2520
|
-
/**
|
|
2521
|
-
* @param read The settings document.
|
|
2522
|
-
* @param poolRows The pool's own rows, needed only to resolve a chain member
|
|
2523
|
-
* that names a WorkBuddy model. A chain may mix pool models with aggregate
|
|
2524
|
-
* ones, so without this a perfectly valid chain would lose its pool half.
|
|
2525
|
-
*/
|
|
2526
|
-
constructor(read: () => AggregateStore | Promise<AggregateStore>, poolRows?: () => readonly WorkBuddyModelInfo[]);
|
|
2527
|
-
/**
|
|
2528
|
-
* Every row this catalog offers: third-party rows first, then chain rows.
|
|
2529
|
-
*
|
|
2530
|
-
* Chains come last so a picker listing stays readable — a chain is a
|
|
2531
|
-
* convenience over models the user already has listed, not a new vendor.
|
|
2532
|
-
*/
|
|
2533
|
-
current(): readonly (AggregateModelRow | ComboModelRow)[];
|
|
2534
|
-
/** Only the third-party rows, which is what the aggregate resolver needs. */
|
|
2535
|
-
providerRows(): readonly AggregateModelRow[];
|
|
2536
|
-
/** Only the chain rows. */
|
|
2537
|
-
comboRows(): readonly ComboModelRow[];
|
|
2538
|
-
/** Re-read the store and notify listeners when the roster actually changed. */
|
|
2539
|
-
refresh(): Promise<readonly (AggregateModelRow | ComboModelRow)[]>;
|
|
2540
|
-
private listeners;
|
|
2541
|
-
onChange(listener: () => void): () => void;
|
|
2542
|
-
/** One third-party row by composite id, or undefined. */
|
|
2543
|
-
find(id: string): AggregateModelRow | undefined;
|
|
2544
|
-
/** One chain row by combo id, or undefined. */
|
|
2545
|
-
findCombo(id: string): ComboModelRow | undefined;
|
|
2546
|
-
/** Whether any provider or chain is serving anything right now. */
|
|
2547
|
-
hasRows(): boolean;
|
|
2548
|
-
}
|
|
2549
|
-
//#endregion
|
|
2550
2733
|
//#region src/stats.d.ts
|
|
2551
2734
|
/**
|
|
2552
2735
|
* Per-call usage accounting for the chat path.
|
|
@@ -2587,7 +2770,18 @@ interface TokenUsage {
|
|
|
2587
2770
|
}
|
|
2588
2771
|
/** One upstream HTTP round trip, successful or not. */
|
|
2589
2772
|
interface UsageCall {
|
|
2590
|
-
/**
|
|
2773
|
+
/**
|
|
2774
|
+
* Which CHANNEL served the call: `workbuddy`, `free`, or a provider id.
|
|
2775
|
+
*
|
|
2776
|
+
* Until this existed the ledger could only say `地区` (domestic /
|
|
2777
|
+
* international), which is a property of the WorkBuddy pool and of nothing
|
|
2778
|
+
* else. Every row therefore read `国内版` even when the call had gone to a
|
|
2779
|
+
* third-party vendor or to the keyless lane, and the only honest reading of the
|
|
2780
|
+
* table was "the other channels are not recorded at all" — which was true:
|
|
2781
|
+
* only the pool and the free lane ever called `record`.
|
|
2782
|
+
*/
|
|
2783
|
+
channel: string;
|
|
2784
|
+
/** Which WorkBuddy gateway served it: `cn` or `global`; empty for other lanes. */
|
|
2591
2785
|
region: string;
|
|
2592
2786
|
/** The model id the request asked for. */
|
|
2593
2787
|
model: string;
|
|
@@ -2621,6 +2815,14 @@ interface UsageCall {
|
|
|
2621
2815
|
}
|
|
2622
2816
|
/** One row of the per-model aggregate. */
|
|
2623
2817
|
interface UsageRow {
|
|
2818
|
+
/**
|
|
2819
|
+
* The channel this row is about: `workbuddy`, `free`, or a provider id.
|
|
2820
|
+
*
|
|
2821
|
+
* Part of the grouping key, not just a label. Two vendors can publish the same
|
|
2822
|
+
* model id, and the pool and the free lane can both serve `glm-5.3` — summing
|
|
2823
|
+
* them into one row would attribute a third-party vendor's tokens to WorkBuddy.
|
|
2824
|
+
*/
|
|
2825
|
+
channel: string;
|
|
2624
2826
|
region: string;
|
|
2625
2827
|
model: string;
|
|
2626
2828
|
/** Physical upstream calls. */
|
|
@@ -2646,6 +2848,14 @@ interface UsageRow {
|
|
|
2646
2848
|
interface UsageAccountRow {
|
|
2647
2849
|
/** Display label of the account, as the pool prints it. */
|
|
2648
2850
|
account: string;
|
|
2851
|
+
/**
|
|
2852
|
+
* The channel this account belongs to.
|
|
2853
|
+
*
|
|
2854
|
+
* Part of the grouping key: a provider's key and a pool account are different
|
|
2855
|
+
* things even when both are labelled, and `free` is not a WorkBuddy account at
|
|
2856
|
+
* all.
|
|
2857
|
+
*/
|
|
2858
|
+
channel: string;
|
|
2649
2859
|
/** Region the account belongs to; an account serves one gateway. */
|
|
2650
2860
|
region: string;
|
|
2651
2861
|
/** Physical calls this account served. */
|
|
@@ -2757,6 +2967,60 @@ declare class UsageRecorder {
|
|
|
2757
2967
|
private days;
|
|
2758
2968
|
}
|
|
2759
2969
|
//#endregion
|
|
2970
|
+
//#region src/aggregate.d.ts
|
|
2971
|
+
/** Registry `format` → the wire vocabulary this module speaks. */
|
|
2972
|
+
type AggregateWire = 'chat' | 'responses' | 'messages';
|
|
2973
|
+
/** One model the aggregate lane offers. */
|
|
2974
|
+
interface AggregateModelRow {
|
|
2975
|
+
/** Composite id: `providerId/modelId`, which is also the picker id. */
|
|
2976
|
+
id: string;
|
|
2977
|
+
/** Display name: the provider's own name plus the row's label. */
|
|
2978
|
+
name: string;
|
|
2979
|
+
providerId: string;
|
|
2980
|
+
modelId: string;
|
|
2981
|
+
contextWindow: number;
|
|
2982
|
+
maxOutputTokens: number;
|
|
2983
|
+
supportsImages: boolean;
|
|
2984
|
+
wire: AggregateWire;
|
|
2985
|
+
/** `static` from the registry, `discovered` from a live listing. */
|
|
2986
|
+
source: 'static' | 'discovered';
|
|
2987
|
+
}
|
|
2988
|
+
/** One stored aggregate row set, refreshed on change, for the shim and adapter. */
|
|
2989
|
+
declare class AggregateCatalog {
|
|
2990
|
+
private readonly read;
|
|
2991
|
+
private readonly poolRows;
|
|
2992
|
+
private rows;
|
|
2993
|
+
private chainRows;
|
|
2994
|
+
/**
|
|
2995
|
+
* @param read The settings document.
|
|
2996
|
+
* @param poolRows The pool's own rows, needed only to resolve a chain member
|
|
2997
|
+
* that names a WorkBuddy model. A chain may mix pool models with aggregate
|
|
2998
|
+
* ones, so without this a perfectly valid chain would lose its pool half.
|
|
2999
|
+
*/
|
|
3000
|
+
constructor(read: () => AggregateStore | Promise<AggregateStore>, poolRows?: () => readonly WorkBuddyModelInfo[]);
|
|
3001
|
+
/**
|
|
3002
|
+
* Every row this catalog offers: third-party rows first, then chain rows.
|
|
3003
|
+
*
|
|
3004
|
+
* Chains come last so a picker listing stays readable — a chain is a
|
|
3005
|
+
* convenience over models the user already has listed, not a new vendor.
|
|
3006
|
+
*/
|
|
3007
|
+
current(): readonly (AggregateModelRow | ComboModelRow)[];
|
|
3008
|
+
/** Only the third-party rows, which is what the aggregate resolver needs. */
|
|
3009
|
+
providerRows(): readonly AggregateModelRow[];
|
|
3010
|
+
/** Only the chain rows. */
|
|
3011
|
+
comboRows(): readonly ComboModelRow[];
|
|
3012
|
+
/** Re-read the store and notify listeners when the roster actually changed. */
|
|
3013
|
+
refresh(): Promise<readonly (AggregateModelRow | ComboModelRow)[]>;
|
|
3014
|
+
private listeners;
|
|
3015
|
+
onChange(listener: () => void): () => void;
|
|
3016
|
+
/** One third-party row by composite id, or undefined. */
|
|
3017
|
+
find(id: string): AggregateModelRow | undefined;
|
|
3018
|
+
/** One chain row by combo id, or undefined. */
|
|
3019
|
+
findCombo(id: string): ComboModelRow | undefined;
|
|
3020
|
+
/** Whether any provider or chain is serving anything right now. */
|
|
3021
|
+
hasRows(): boolean;
|
|
3022
|
+
}
|
|
3023
|
+
//#endregion
|
|
2760
3024
|
//#region src/channel-lane.d.ts
|
|
2761
3025
|
/** One model as the gateway lists and routes it. */
|
|
2762
3026
|
interface ChannelLaneRow {
|
|
@@ -3160,6 +3424,16 @@ interface AutomationJobState {
|
|
|
3160
3424
|
* is the question the panel exists to answer.
|
|
3161
3425
|
*/
|
|
3162
3426
|
detail?: readonly string[];
|
|
3427
|
+
/**
|
|
3428
|
+
* The same work with a status per item.
|
|
3429
|
+
*
|
|
3430
|
+
* `detail` is a flat list of sentences, so the card can print it but cannot
|
|
3431
|
+
* group it. This carries `claimed` / `already` / `skipped` / `failed` per
|
|
3432
|
+
* thing the job looked at, which is what separates "everything was already
|
|
3433
|
+
* done" from "nothing was claimable" from "the endpoint is down" — three
|
|
3434
|
+
* outcomes that all print as "0 claimed".
|
|
3435
|
+
*/
|
|
3436
|
+
items?: readonly PoolWebAutomationItem[];
|
|
3163
3437
|
/**
|
|
3164
3438
|
* A pending milestone worth naming, when there is one.
|
|
3165
3439
|
*
|
|
@@ -3522,6 +3796,10 @@ export declare class WorkBuddyScheduler {
|
|
|
3522
3796
|
*
|
|
3523
3797
|
* Disabled accounts are excluded here rather than filtered by the caller so a
|
|
3524
3798
|
* card switch takes effect on the next pass without any event plumbing.
|
|
3799
|
+
*
|
|
3800
|
+
* `job` narrows the set by region scope: the growth jobs are CN-only while
|
|
3801
|
+
* check-in runs on both gateways, so eligibility cannot be decided without
|
|
3802
|
+
* knowing which job is about to run.
|
|
3525
3803
|
*/
|
|
3526
3804
|
private accountsInOrder;
|
|
3527
3805
|
/**
|
|
@@ -3564,6 +3842,25 @@ export declare class WorkBuddyScheduler {
|
|
|
3564
3842
|
* logs "could not be built" only for exceptions, and a task shape this code
|
|
3565
3843
|
* does not understand is information, not a fault.
|
|
3566
3844
|
*/
|
|
3845
|
+
/**
|
|
3846
|
+
* Find the expert a task is about, by matching its title against the
|
|
3847
|
+
* marketplace.
|
|
3848
|
+
*
|
|
3849
|
+
* The marketplace listing is ~500 entries across `agent` and `team`, and this
|
|
3850
|
+
* only runs for a task whose deeplink carried no id — at most a handful per
|
|
3851
|
+
* run — so the cost is acceptable. It is not cached because a freshly
|
|
3852
|
+
* published expert must become findable without a restart.
|
|
3853
|
+
*
|
|
3854
|
+
* Matching rules, all of them strict on purpose:
|
|
3855
|
+
* - the task's title must appear IN the expert's name or profession, or the
|
|
3856
|
+
* expert's display name must appear in the title (both directions, since
|
|
3857
|
+
* the board and the marketplace word things differently);
|
|
3858
|
+
* - comparison ignores case, whitespace and the punctuation vendors sprinkle
|
|
3859
|
+
* through names;
|
|
3860
|
+
* - several matches means NO answer. Summoning the wrong agent scores 0, so a
|
|
3861
|
+
* guess costs an upstream call and still fails — worse than declining.
|
|
3862
|
+
*/
|
|
3863
|
+
private expertIdByKeyword;
|
|
3567
3864
|
private taskExpertChains;
|
|
3568
3865
|
/**
|
|
3569
3866
|
* The summon-and-use chains for the expert tasks.
|
|
@@ -3960,7 +4257,16 @@ interface PoolStatusRouteOptions {
|
|
|
3960
4257
|
* a chain name, and does what it names still exist" — and answering them from
|
|
3961
4258
|
* two snapshots could show a member that the chains no longer resolve.
|
|
3962
4259
|
*/
|
|
3963
|
-
|
|
4260
|
+
/**
|
|
4261
|
+
* The routing document.
|
|
4262
|
+
*
|
|
4263
|
+
* May return a PROMISE: login-channel rows come from the host's
|
|
4264
|
+
* `llm.listModels`, which is asynchronous, and a chain that cannot name TRAE or
|
|
4265
|
+
* Qoder is precisely the defect this document had. A synchronous build keeps
|
|
4266
|
+
* returning the object directly, so both shapes are accepted rather than forcing
|
|
4267
|
+
* every caller to become async.
|
|
4268
|
+
*/
|
|
4269
|
+
combosDocument?: () => PoolWebCombosStatus | Promise<PoolWebCombosStatus>;
|
|
3964
4270
|
/**
|
|
3965
4271
|
* Replace the chain table and refresh the running catalog, then re-answer the
|
|
3966
4272
|
* document. The catalog refresh is what makes a new chain pickable at once.
|
|
@@ -4082,6 +4388,15 @@ export interface Config {
|
|
|
4082
4388
|
* does not wipe what the automation already earned.
|
|
4083
4389
|
*/
|
|
4084
4390
|
automationEarnings?: AutomationLedger;
|
|
4391
|
+
/**
|
|
4392
|
+
* Whether the shared 免密 free lane contributes models.
|
|
4393
|
+
*
|
|
4394
|
+
* Absent reads as OFF. It is the only lane that defaults off: it is a shared
|
|
4395
|
+
* third-party endpoint with no credential of the user's own, so leaving it on
|
|
4396
|
+
* dropped a group into the model picker that nothing in the UI could remove
|
|
4397
|
+
* (the aggregate switch does not govern it — it is not an aggregate provider).
|
|
4398
|
+
*/
|
|
4399
|
+
freeLane?: boolean;
|
|
4085
4400
|
}
|
|
4086
4401
|
/** One region's saved model selection. */
|
|
4087
4402
|
export interface ModelSelectionConfig {
|