dsh-xdpool 2.6.0 → 2.6.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/lib/index.d.ts CHANGED
@@ -858,7 +858,7 @@ export declare const WORKBUDDY_AUTH_FILE_ENV = "WORKBUDDY_AUTH_FILE";
858
858
  */
859
859
  interface WorkBuddySkippedFile {
860
860
  path: string;
861
- reason: 'encrypted' | 'unreadable' | 'malformed';
861
+ reason: 'encrypted' | 'expired' | 'unreadable' | 'malformed';
862
862
  }
863
863
  interface WorkBuddyCredential {
864
864
  accessToken: string;
@@ -1202,6 +1202,19 @@ export declare class WorkBuddyAccountPool {
1202
1202
  * instead of silently showing half a pool.
1203
1203
  */
1204
1204
  skippedFilesInOrder(): readonly WorkBuddySkippedFile[];
1205
+ /**
1206
+ * Delete expired snapshots that a newer credential for the same account supersedes.
1207
+ *
1208
+ * Returns the paths actually removed. See the call site for the full safety rule; the
1209
+ * short version is that it touches ONLY files classified `expired`, ONLY when the same
1210
+ * `uin` is already served by a different (loaded) file, and never a live file.
1211
+ *
1212
+ * `uin` rather than `uid`: it is the billing identity, so two sign-ins of one person
1213
+ * match even when the desktop app wrote them from different installs. A file whose
1214
+ * identity cannot be read is left alone — deleting a credential on a guess is worse than
1215
+ * keeping a dead one on the card.
1216
+ */
1217
+ private pruneExpiredSnapshots;
1205
1218
  /** Rescan the auth directories and merge newly discovered accounts. */
1206
1219
  scan(): Promise<WorkBuddyAccount[]>;
1207
1220
  /** All accounts, cooldown state included. */
@@ -1216,6 +1229,39 @@ export declare class WorkBuddyAccountPool {
1216
1229
  * model, e.g. CLI diagnostics).
1217
1230
  */
1218
1231
  private available;
1232
+ /**
1233
+ * The pool ordered into three bands, so a resting account is deferred instead of
1234
+ * discarded.
1235
+ *
1236
+ * `available()` answers a binary question, and a binary answer loses the
1237
+ * distinction that matters most when a pool is under pressure:
1238
+ *
1239
+ * - an account that still HAS credits but was rate-limited a moment ago is
1240
+ * healthy — it should be tried AFTER the others, not treated as gone;
1241
+ * - an account resting after a failure is the last resort, but it is still a
1242
+ * resort: when it is the only one, trying it beats failing the request.
1243
+ *
1244
+ * A pool that drops both from the list turns "every account is cooling for
1245
+ * twenty more seconds" into an error the user reads as "no account available",
1246
+ * which is a different and much more alarming statement.
1247
+ *
1248
+ * The bands:
1249
+ *
1250
+ * 1. `ready` — passes every gate `available()` checks.
1251
+ * 2. `limited` — region-eligible and not disabled/reserved, but cooling for
1252
+ * this model or account-wide. Ordered by when it comes back,
1253
+ * so the account that recovers first is spent first.
1254
+ * 3. `resting` — sign-in was rejected by the upstream. It never heals on a
1255
+ * timer, so it is only tried when 1 and 2 are both empty.
1256
+ *
1257
+ * `disabled` and `reserve` accounts appear in NO band: those are user choices,
1258
+ * and overriding them is not resilience, it is ignoring an instruction.
1259
+ *
1260
+ * Kept separate from `available()` rather than replacing it, so the binary
1261
+ * question still has a binary answer for callers that want one (diagnostics,
1262
+ * the status document) without either copy drifting from the other.
1263
+ */
1264
+ private rankedPool;
1219
1265
  /**
1220
1266
  * Why no account is available right now, for an accurate error.
1221
1267
  *
@@ -1324,6 +1370,13 @@ export declare class WorkBuddyAccountPool {
1324
1370
  * `conversationKey` is only consulted under `sticky`; other modes ignore it.
1325
1371
  */
1326
1372
  acquire(modelId?: string, region?: WorkBuddyRegion, conversationKey?: string, reserveExempt?: ReadonlySet<string>): Promise<WorkBuddyAccount | undefined>;
1373
+ /**
1374
+ * Whether an account belongs to a band that is currently in play.
1375
+ *
1376
+ * Only `ready` accounts are eligible for the probe shortcut: picking a resting
1377
+ * account ahead of a healthy one is the very thing the bands exist to prevent.
1378
+ */
1379
+ private isStageEligible;
1327
1380
  /** How the pool currently spreads requests. Shown on the card. */
1328
1381
  currentDistribution(): AccountDistribution;
1329
1382
  /**
@@ -2206,7 +2259,7 @@ interface PoolWebStatus {
2206
2259
  interface PoolWebSkippedFile {
2207
2260
  /** Basename only; the full path lives in the desktop app's auth directory. */
2208
2261
  file: string;
2209
- reason: 'encrypted' | 'unreadable' | 'malformed';
2262
+ reason: 'encrypted' | 'expired' | 'unreadable' | 'malformed';
2210
2263
  }
2211
2264
  /** How a region's model list was obtained. */
2212
2265
  type PoolWebCatalogSource = 'live' | 'fallback';
@@ -4272,6 +4325,15 @@ interface PoolStatusRouteOptions {
4272
4325
  * document. The catalog refresh is what makes a new chain pickable at once.
4273
4326
  */
4274
4327
  saveCombos?: (raw: unknown) => Promise<PoolWebCombosStatus>;
4328
+ /**
4329
+ * Estimated credit spend per channel and model, for the composer strip.
4330
+ *
4331
+ * Its own endpoint rather than a field of the status document: the pool card polls
4332
+ * status every 30 seconds, and the ledger roll-up would be recomputed on every one
4333
+ * of those polls for a number that changes once per request. The strip asks on its
4334
+ * own cadence.
4335
+ */
4336
+ creditsSpend?: (days: number | undefined) => Promise<unknown>;
4275
4337
  /**
4276
4338
  * The relay's current state, or undefined when this build has no relay.
4277
4339
  *