maxpool 1.12.0 → 1.13.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/package.json +1 -1
- package/src/account-manager.js +77 -17
- package/src/capacity-ledger.js +68 -2
- package/src/tui.js +64 -51
package/package.json
CHANGED
package/src/account-manager.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { refreshAccessToken, isTokenExpiringSoon, modelFamily, tokenFingerprint } from './oauth.js';
|
|
2
|
-
import { CapacityLedger } from './capacity-ledger.js';
|
|
2
|
+
import { CapacityLedger, TANK_MIN_UTIL } from './capacity-ledger.js';
|
|
3
3
|
|
|
4
4
|
// Nominal window length per kind — mirrors capacity-ledger's WINDOW_MS (kept here as a
|
|
5
5
|
// local table so account-manager does not import a private constant).
|
|
@@ -1134,7 +1134,10 @@ export class AccountManager {
|
|
|
1134
1134
|
// disappears (without this, OAuth cycles essentially never close: red-team 2026-08-22).
|
|
1135
1135
|
if (q.unified5h != null && q.unified5hReset && now >= q.unified5hReset) {
|
|
1136
1136
|
console.log(`[Maxpool] Account "${account.name}" session quota reset`);
|
|
1137
|
-
|
|
1137
|
+
// TANK: q.unified5h is still the CLOSING window's fullness here — the nulls below
|
|
1138
|
+
// come after. Snapshot into the cycle before the rollover wipes it.
|
|
1139
|
+
this.capacity?.closeCycle?.(account.name, 'ses', q.unified5hReset,
|
|
1140
|
+
{ resetAt: q.unified5hReset, finalUtilization: q.unified5h });
|
|
1138
1141
|
q.unified5h = null;
|
|
1139
1142
|
q.unified5hReset = null;
|
|
1140
1143
|
changed = true;
|
|
@@ -1142,7 +1145,8 @@ export class AccountManager {
|
|
|
1142
1145
|
}
|
|
1143
1146
|
if (q.unified7d != null && q.unified7dReset && now >= q.unified7dReset) {
|
|
1144
1147
|
console.log(`[Maxpool] Account "${account.name}" weekly quota reset`);
|
|
1145
|
-
this.capacity?.closeCycle?.(account.name, 'wk', q.unified7dReset,
|
|
1148
|
+
this.capacity?.closeCycle?.(account.name, 'wk', q.unified7dReset,
|
|
1149
|
+
{ resetAt: q.unified7dReset, finalUtilization: q.unified7d });
|
|
1146
1150
|
q.unified7d = null;
|
|
1147
1151
|
q.unified7dReset = null;
|
|
1148
1152
|
q.unifiedStatus = null;
|
|
@@ -2667,7 +2671,7 @@ export class AccountManager {
|
|
|
2667
2671
|
* in-window) and criticalPeakUnlock is enabled. Default off.
|
|
2668
2672
|
* Precedence prereset > pressure > peak: the cheaper drain wins.
|
|
2669
2673
|
*/
|
|
2670
|
-
_criticalUnlock(account, requestInfo = {}, excludedIndexes = new Set(),
|
|
2674
|
+
_criticalUnlock(account, requestInfo = {}, excludedIndexes = new Set(), _pressureCache = null, now = Date.now()) {
|
|
2671
2675
|
const state = this._weeklyRawState(account);
|
|
2672
2676
|
if (state !== 'critical') return null;
|
|
2673
2677
|
|
|
@@ -2736,7 +2740,7 @@ export class AccountManager {
|
|
|
2736
2740
|
* - pressure/peak: a flat cost ABOVE reserve's attainable max, so critical is
|
|
2737
2741
|
* relief for a LOADED last route and never preempts an idle reserve.
|
|
2738
2742
|
*/
|
|
2739
|
-
_criticalCost(account,
|
|
2743
|
+
_criticalCost(account, _now = Date.now(), unlock = null, weeklyState = this._weeklyRawState(account)) {
|
|
2740
2744
|
if (weeklyState !== 'critical') return 0;
|
|
2741
2745
|
if (!unlock) return 0;
|
|
2742
2746
|
if (unlock.reason === 'prereset') {
|
|
@@ -2915,10 +2919,14 @@ export class AccountManager {
|
|
|
2915
2919
|
const account = this.accounts[accountIndex];
|
|
2916
2920
|
if (!account || !usage) return;
|
|
2917
2921
|
const q = account.quota;
|
|
2918
|
-
// CAPACITY LEDGER: prev stamps, so a probe observing the
|
|
2919
|
-
// the old cycle
|
|
2922
|
+
// CAPACITY LEDGER: prev stamps AND prev utilizations, so a probe observing the
|
|
2923
|
+
// window ADVANCE closes the old cycle with the OLD window's tank reading —
|
|
2924
|
+
// snapshot BEFORE the writes below clobber the fields with the new window's
|
|
2925
|
+
// values (the OAuth twin of the applyProviderUsage hook).
|
|
2920
2926
|
const prevSesReset = q.unified5hReset;
|
|
2921
2927
|
const prevWkReset = q.unified7dReset;
|
|
2928
|
+
const prevSesUtil = q.unified5h;
|
|
2929
|
+
const prevWkUtil = q.unified7d;
|
|
2922
2930
|
|
|
2923
2931
|
if (usage.fiveHour) {
|
|
2924
2932
|
if (usage.fiveHour.utilization != null) q.unified5h = clamp01(usage.fiveHour.utilization);
|
|
@@ -2928,8 +2936,8 @@ export class AccountManager {
|
|
|
2928
2936
|
if (usage.sevenDay.utilization != null) q.unified7d = clamp01(usage.sevenDay.utilization);
|
|
2929
2937
|
if (usage.sevenDay.resetAt != null) q.unified7dReset = usage.sevenDay.resetAt;
|
|
2930
2938
|
}
|
|
2931
|
-
this.noteCapacityWindowAdvance(account.name, 'ses', prevSesReset, usage.fiveHour?.resetAt);
|
|
2932
|
-
this.noteCapacityWindowAdvance(account.name, 'wk', prevWkReset, usage.sevenDay?.resetAt);
|
|
2939
|
+
this.noteCapacityWindowAdvance(account.name, 'ses', prevSesReset, usage.fiveHour?.resetAt, prevSesUtil);
|
|
2940
|
+
this.noteCapacityWindowAdvance(account.name, 'wk', prevWkReset, usage.sevenDay?.resetAt, prevWkUtil);
|
|
2933
2941
|
// Utilization readings feed the capacity ESTIMATE. The probe path passes per-window
|
|
2934
2942
|
// marks so the DELTA method can difference consecutive readings.
|
|
2935
2943
|
this.capacity.noteUtilizationObserved(Date.now(), [
|
|
@@ -3046,11 +3054,14 @@ export class AccountManager {
|
|
|
3046
3054
|
const account = this.accounts[accountIndex];
|
|
3047
3055
|
if (!account || !usage) return;
|
|
3048
3056
|
const q = account.quota;
|
|
3049
|
-
// CAPACITY LEDGER: snapshot the previous reset stamps so a probe
|
|
3050
|
-
// window ADVANCE (new stamp) closes the capacity cycle at the old
|
|
3051
|
-
//
|
|
3057
|
+
// CAPACITY LEDGER: snapshot the previous reset stamps AND utilizations so a probe
|
|
3058
|
+
// observing the window ADVANCE (new stamp) closes the capacity cycle at the old
|
|
3059
|
+
// boundary WITH the old window's tank reading — covers windows whose old stamp
|
|
3060
|
+
// was never learned (clock-close can't fire). Snapshot before the writes below.
|
|
3052
3061
|
const prevSesReset = q.providerSesReset;
|
|
3053
3062
|
const prevWkReset = q.providerWkReset;
|
|
3063
|
+
const prevSesUtil = q.providerSes;
|
|
3064
|
+
const prevWkUtil = q.providerWk;
|
|
3054
3065
|
if (usage.error) {
|
|
3055
3066
|
// Distinguish "no pollable quota" (Kimi) from a transient probe failure.
|
|
3056
3067
|
// Never clear existing values on a transient error — let them age into the
|
|
@@ -3078,8 +3089,8 @@ export class AccountManager {
|
|
|
3078
3089
|
q.weeklyAbsent = true;
|
|
3079
3090
|
}
|
|
3080
3091
|
q.lastProbeOkAt = Date.now();
|
|
3081
|
-
this.noteCapacityWindowAdvance(account.name, 'ses', prevSesReset, usage.ses?.resetAt);
|
|
3082
|
-
this.noteCapacityWindowAdvance(account.name, 'wk', prevWkReset, usage.wk?.resetAt);
|
|
3092
|
+
this.noteCapacityWindowAdvance(account.name, 'ses', prevSesReset, usage.ses?.resetAt, prevSesUtil);
|
|
3093
|
+
this.noteCapacityWindowAdvance(account.name, 'wk', prevWkReset, usage.wk?.resetAt, prevWkUtil);
|
|
3083
3094
|
this.capacity.noteUtilizationObserved(Date.now(), [
|
|
3084
3095
|
{ name: account.name, window: 'ses', utilization: usage.ses?.utilization },
|
|
3085
3096
|
{ name: account.name, window: 'wk', utilization: usage.wk?.utilization },
|
|
@@ -3277,6 +3288,28 @@ export class AccountManager {
|
|
|
3277
3288
|
return this.capacity.estimateFromUtilization(a.name, window, util) || null;
|
|
3278
3289
|
}
|
|
3279
3290
|
|
|
3291
|
+
/** Measured TANK for an account+window: capacity, not delivery. Prefers completed
|
|
3292
|
+
* cycles (tokens ÷ closing utilization, averaged); falls back to the live open
|
|
3293
|
+
* window's estimate so a row is useful from minute one instead of reading
|
|
3294
|
+
* "no completed cycle yet" while the vendor is plainly reporting a percentage. */
|
|
3295
|
+
capacityTank(accountIndex, window) {
|
|
3296
|
+
const a = this.accounts[accountIndex];
|
|
3297
|
+
if (!a) return null;
|
|
3298
|
+
const measured = this.capacity.tankStats(a.name, window);
|
|
3299
|
+
if (measured) return { ...measured, source: 'cycles' };
|
|
3300
|
+
const est = this.capacityEstimate(accountIndex, window);
|
|
3301
|
+
if (!est) return null;
|
|
3302
|
+
// Same rounding-noise guard as tankStats: a 1%-full window divides by vendor
|
|
3303
|
+
// whole-percent rounding and can read absurd (measured live: 455k ÷ 1% = "≥45M").
|
|
3304
|
+
// Below the floor the reading is noise — withhold rather than print a fiction.
|
|
3305
|
+
if (est.utilization < TANK_MIN_UTIL) return null;
|
|
3306
|
+
return {
|
|
3307
|
+
avg: est.tokens, last: est.tokens, n: 0, exact: est.lowerBound ? 0 : 1,
|
|
3308
|
+
bounded: est.lowerBound ? 1 : 0, lowerBound: Boolean(est.lowerBound),
|
|
3309
|
+
source: 'live', utilization: est.utilization, method: est.method, fresh: est.fresh,
|
|
3310
|
+
};
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3280
3313
|
accrueCapacity(accountIndex, { input = 0, output = 0 } = {}) {
|
|
3281
3314
|
const account = this.accounts[accountIndex];
|
|
3282
3315
|
if (!account) return;
|
|
@@ -3289,6 +3322,18 @@ export class AccountManager {
|
|
|
3289
3322
|
this.capacity.accrue(account.name, { input, output }, undefined, windows);
|
|
3290
3323
|
}
|
|
3291
3324
|
|
|
3325
|
+
/** The vendor's CURRENT fullness reading for a window — the tank numerator's
|
|
3326
|
+
* denominator. Returns null when unreadable (a null reading divides nothing and
|
|
3327
|
+
* must never coerce to 0, which would make tank = Infinity). */
|
|
3328
|
+
_windowUtilization(account, window) {
|
|
3329
|
+
const q = account?.quota;
|
|
3330
|
+
if (!q) return null;
|
|
3331
|
+
const v = account.type === 'provider'
|
|
3332
|
+
? (window === 'wk' ? q.providerWk : q.providerSes)
|
|
3333
|
+
: (window === 'wk' ? q.unified7d : q.unified5h);
|
|
3334
|
+
return Number.isFinite(v) && v >= 0 ? v : null;
|
|
3335
|
+
}
|
|
3336
|
+
|
|
3292
3337
|
/** Close any window cycle whose reset time has passed — CLOCK-AUTHORITATIVE, so a
|
|
3293
3338
|
* stale or dead probe can never leave a cycle open and mis-attribute the next
|
|
3294
3339
|
* window's tokens to it (pre-mortem M5; worst case is the no-weekly account whose
|
|
@@ -3332,7 +3377,14 @@ export class AccountManager {
|
|
|
3332
3377
|
// here as well (round-2) made a prober-first notice silently swallow all of
|
|
3333
3378
|
// those whenever the sweep won the race (red-team round 3, RT3-1).
|
|
3334
3379
|
if (resetAt && now >= resetAt) {
|
|
3335
|
-
this.capacity.closeCycle(a.name, win, resetAt, {
|
|
3380
|
+
this.capacity.closeCycle(a.name, win, resetAt, {
|
|
3381
|
+
resetAt,
|
|
3382
|
+
// TANK: the vendor's own fullness for the window we are closing. Read it
|
|
3383
|
+
// BEFORE _clearExpiredQuotas nulls it — this sweep runs first by design
|
|
3384
|
+
// (see the close-only note above), which is exactly why the reading is
|
|
3385
|
+
// still the CLOSING window's and not the new one's.
|
|
3386
|
+
finalUtilization: this._windowUtilization(a, win),
|
|
3387
|
+
});
|
|
3336
3388
|
}
|
|
3337
3389
|
}
|
|
3338
3390
|
}
|
|
@@ -3340,7 +3392,7 @@ export class AccountManager {
|
|
|
3340
3392
|
|
|
3341
3393
|
/** Close a cycle because a probe observed the window ADVANCE (a new reset stamp) —
|
|
3342
3394
|
* covers the case where the old stamp was never learned. */
|
|
3343
|
-
noteCapacityWindowAdvance(accountName, window, prevResetAt, nextResetAt) {
|
|
3395
|
+
noteCapacityWindowAdvance(accountName, window, prevResetAt, nextResetAt, prevUtilization = null) {
|
|
3344
3396
|
if (!prevResetAt || !nextResetAt) return;
|
|
3345
3397
|
// TWO guards, both learned from live data (2026-08-23):
|
|
3346
3398
|
// 1. PAST stamp = a probe that answered late (its window rolled mid-request) or
|
|
@@ -3361,7 +3413,15 @@ export class AccountManager {
|
|
|
3361
3413
|
// expired) — endedAt is always within [start, now].
|
|
3362
3414
|
const boundary = Math.min(nextResetAt, nowMs);
|
|
3363
3415
|
if (boundary - prevResetAt < WINDOW_ADVANCE_EPSILON_MS) return;
|
|
3364
|
-
|
|
3416
|
+
// TANK: the CLOSING window's own fullness, passed in by the caller. It must be the
|
|
3417
|
+
// caller's SNAPSHOT, never a re-read here: both probe paths write the new window's
|
|
3418
|
+
// utilization into the quota fields before calling us, so re-reading would divide
|
|
3419
|
+
// the old window's tokens by the NEW window's percentage — a silently wrong tank
|
|
3420
|
+
// on exactly the rollover this path exists to catch.
|
|
3421
|
+
this.capacity.closeCycle(accountName, window, boundary, {
|
|
3422
|
+
resetAt: prevResetAt,
|
|
3423
|
+
finalUtilization: Number.isFinite(prevUtilization) && prevUtilization >= 0 ? prevUtilization : null,
|
|
3424
|
+
});
|
|
3365
3425
|
}
|
|
3366
3426
|
|
|
3367
3427
|
/**
|
package/src/capacity-ledger.js
CHANGED
|
@@ -35,6 +35,14 @@ const SAME_BOUNDARY_MS = 5_000;
|
|
|
35
35
|
// The minimum span of a COMPLETE cycle per window (80% of nominal): a real one is
|
|
36
36
|
// flagged partial by the writer, so a complete cycle below this is corrupt history.
|
|
37
37
|
const READ_FLOOR_MS = { ses: 4 * 3600_000, wk: 5 * 86400_000 };
|
|
38
|
+
|
|
39
|
+
// TANK floor. tank = tokens ÷ utilization, and vendors report WHOLE percents — so at
|
|
40
|
+
// 1% full, one percentage point of rounding swings the answer by 100% (measured live
|
|
41
|
+
// 2026-08-25: a 1%-full window read "≥45M"). Below this the reading is rounding noise,
|
|
42
|
+
// not a measurement. Exported because BOTH the closed-cycle average and the live
|
|
43
|
+
// in-window estimate must apply the same floor; one guarding without the other is how
|
|
44
|
+
// the absurd number reached the screen in the first place.
|
|
45
|
+
export const TANK_MIN_UTIL = 0.05;
|
|
38
46
|
const MAX_CYCLES_PER_WINDOW = 50;
|
|
39
47
|
const MAX_DAY_BUCKETS = 10;
|
|
40
48
|
|
|
@@ -199,8 +207,15 @@ export class CapacityLedger {
|
|
|
199
207
|
|
|
200
208
|
/** Close the open cycle for a window (M5: clock-authoritative — the close is keyed
|
|
201
209
|
* on `endedAt`, which the caller derives from the reset stamp or the clock, and the
|
|
202
|
-
* cycle keeps its own book regardless of probe health). No-op if none open.
|
|
203
|
-
|
|
210
|
+
* cycle keeps its own book regardless of probe health). No-op if none open.
|
|
211
|
+
*
|
|
212
|
+
* TANK (2026-08-25, owner-directed): the closed row records `finalUtilization` —
|
|
213
|
+
* the vendor's own fullness reading for the window at close. tank = tokens ÷ util
|
|
214
|
+
* is the CAPACITY of the plan, as distinct from the tokens we happened to deliver.
|
|
215
|
+
* Delivery measures demand; tank measures the plan. Both are recorded; the UI
|
|
216
|
+
* decides which to show. Recording happens on a best-effort basis here (the ledger
|
|
217
|
+
* keeps its own book — the caller passes the reading in, it does not poll). */
|
|
218
|
+
closeCycle(name, window, endedAt = this._now(), { resetAt = null, finalUtilization = null } = {}) {
|
|
204
219
|
const rec = this._accounts.get(name);
|
|
205
220
|
if (!rec || !rec[window]?.open) return null;
|
|
206
221
|
const open = rec[window].open;
|
|
@@ -221,7 +236,10 @@ export class CapacityLedger {
|
|
|
221
236
|
// Fold ONLY a complete tail: folding a partial/disabled tail would flip the
|
|
222
237
|
// flags on the prior legitimate observation and ERASE it from the averages
|
|
223
238
|
// (round 3, RT3-2) — strictly worse than leaving a tiny excluded cycle.
|
|
239
|
+
// The fold ALSO takes the tail's tank reading if the prior row lacks one —
|
|
240
|
+
// same boundary, same window, so the later reading is simply fresher.
|
|
224
241
|
prev.tokens += open.tokensSoFar;
|
|
242
|
+
if (prev.finalUtilization == null && finalUtilization != null) prev.finalUtilization = finalUtilization;
|
|
225
243
|
rec[window].open = null;
|
|
226
244
|
return prev;
|
|
227
245
|
}
|
|
@@ -232,6 +250,12 @@ export class CapacityLedger {
|
|
|
232
250
|
complete: open.complete,
|
|
233
251
|
disabledDuring: open.disabledDuring,
|
|
234
252
|
...(open.partialReason ? { partialReason: open.partialReason } : {}),
|
|
253
|
+
...(finalUtilization != null ? { finalUtilization } : {}),
|
|
254
|
+
// Carried onto the closed row because tankStats needs it: a cycle observed from
|
|
255
|
+
// its window START yields an EXACT tank; one we joined late yields a lower bound
|
|
256
|
+
// (we only counted the tokens that flowed through maxpool, while the vendor's
|
|
257
|
+
// percentage counts everything). Dropping it here made every tank read "bounded".
|
|
258
|
+
...(open.windowStartedAt != null ? { windowStartedAt: open.windowStartedAt } : {}),
|
|
235
259
|
resetAt,
|
|
236
260
|
});
|
|
237
261
|
if (rec[window].closed.length > MAX_CYCLES_PER_WINDOW) rec[window].closed.shift();
|
|
@@ -366,6 +390,48 @@ export class CapacityLedger {
|
|
|
366
390
|
* ABSENCE (present in dayKeys, absent from days) — and with MAX_DAY_BUCKETS=10 an
|
|
367
391
|
* idle day no longer even evicts; only real activity ages out. `partial` is true
|
|
368
392
|
* when any bucket in the window is flagged partial — the figure is ≤ observed. */
|
|
393
|
+
/** TANK STATS — the CAPACITY of the plan, from the owner's own formula:
|
|
394
|
+
* tank = tokens delivered ÷ utilization at close, per cycle, averaged across
|
|
395
|
+
* cycles (2026-08-25, owner-directed). This measures the plan, not the demand:
|
|
396
|
+
* a cycle that delivered 812k at 96% and one that delivered 51k at 6% both say
|
|
397
|
+
* "~846k tank". Delivered-only averages (windowStats) measure demand and stay
|
|
398
|
+
* available separately.
|
|
399
|
+
*
|
|
400
|
+
* Guards, because the raw formula lies in two ways:
|
|
401
|
+
* - We only count tokens that flowed THROUGH maxpool; a cycle whose vendor util
|
|
402
|
+
* includes spend we never saw (joined mid-window, or usage outside the proxy)
|
|
403
|
+
* yields a tank ≥ the truth but not equal to it. Only a cycle observed from its
|
|
404
|
+
* window start is exact; later ones are marked `lowerBound`.
|
|
405
|
+
* - Vendors report whole percents. At 3% full, 1pp of rounding = 33% error, so a
|
|
406
|
+
* reading below MIN_UTIL is excluded (rounding-dominated) rather than folded
|
|
407
|
+
* into the average as fake precision.
|
|
408
|
+
* Returns { avg, exact, n, bounded, last } or null when no usable readings. */
|
|
409
|
+
tankStats(name, window) {
|
|
410
|
+
const rec = this._accounts.get(name);
|
|
411
|
+
const floor = (this._readFloorOverride ?? READ_FLOOR_MS)[window] ?? 0;
|
|
412
|
+
const usable = (rec?.[window]?.closed || []).filter(c =>
|
|
413
|
+
c.complete && !c.disabledDuring
|
|
414
|
+
&& Number.isFinite(c.finalUtilization)
|
|
415
|
+
&& c.finalUtilization >= TANK_MIN_UTIL
|
|
416
|
+
&& (c.endedAt - c.startedAt) >= floor - 1_000);
|
|
417
|
+
if (!usable.length) return null;
|
|
418
|
+
let sum = 0, exact = 0, bounded = 0;
|
|
419
|
+
for (const c of usable) {
|
|
420
|
+
const observedFromStart = c.startedAt != null && c.windowStartedAt != null
|
|
421
|
+
&& c.startedAt <= c.windowStartedAt + 60_000;
|
|
422
|
+
sum += c.tokens / c.finalUtilization;
|
|
423
|
+
if (observedFromStart) exact++; else bounded++;
|
|
424
|
+
}
|
|
425
|
+
const last = usable[usable.length - 1];
|
|
426
|
+
return {
|
|
427
|
+
avg: Math.round(sum / usable.length),
|
|
428
|
+
exact, bounded,
|
|
429
|
+
n: usable.length,
|
|
430
|
+
last: Math.round(last.tokens / last.finalUtilization),
|
|
431
|
+
lowerBound: bounded > 0 && exact === 0,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
369
435
|
rollingThroughput(name, days = 7) {
|
|
370
436
|
const rec = this._accounts.get(name);
|
|
371
437
|
if (!rec) return { tokens: 0, partial: false };
|
package/src/tui.js
CHANGED
|
@@ -2031,7 +2031,7 @@ export class TUI {
|
|
|
2031
2031
|
const ledger = this.am.capacity;
|
|
2032
2032
|
const title = win === 'wk' ? 'Weekly (7d) capacity' : 'Session (5h) capacity';
|
|
2033
2033
|
out.push('');
|
|
2034
|
-
out.push(` ${bold(title)} ${dim('— tokens
|
|
2034
|
+
out.push(` ${bold(title)} ${dim('— how many tokens each account can deliver per window')}`);
|
|
2035
2035
|
out.push('');
|
|
2036
2036
|
|
|
2037
2037
|
if (!ledger) { out.push(yellow(' Capacity ledger unavailable on this worker.')); return out; }
|
|
@@ -2039,15 +2039,19 @@ export class TUI {
|
|
|
2039
2039
|
// Narrow terminals: drop trailing columns rather than let fitLine chop a number
|
|
2040
2040
|
// mid-digit (at W=80 the full 6-column row is 82+ chars — every row silently lost
|
|
2041
2041
|
// its last two cells). The dropped ones are the aggregates, not the observations.
|
|
2042
|
-
|
|
2043
|
-
|
|
2042
|
+
// CAPACITY (tank) is the headline: tokens ÷ the vendor's own fullness at close,
|
|
2043
|
+
// per cycle. That measures the PLAN. The delivered-token columns measure DEMAND —
|
|
2044
|
+
// useful, but they were the headline before 2026-08-25 and read as capacity, which
|
|
2045
|
+
// is why an account that simply went unused looked small.
|
|
2046
|
+
const ALL_COLS = ['Capacity', 'Used now', 'Last cyc', 'Avg cyc'];
|
|
2047
|
+
const CW = 10;
|
|
2044
2048
|
const nameW = 12;
|
|
2045
2049
|
let COLS = ALL_COLS;
|
|
2046
|
-
while (COLS.length > 1 && (nameW + PROVIDER_W + 2 + COLS.length * CW +
|
|
2050
|
+
while (COLS.length > 1 && (nameW + PROVIDER_W + 2 + COLS.length * CW + 16) > W) {
|
|
2047
2051
|
COLS = COLS.slice(0, -1);
|
|
2048
2052
|
}
|
|
2049
2053
|
const header = ' ' + 'Account'.padEnd(nameW) + ' ' + 'Provider'.padEnd(PROVIDER_W) + ' '
|
|
2050
|
-
+ COLS.map(c => c.padStart(CW)).join('') + '
|
|
2054
|
+
+ COLS.map(c => c.padStart(CW)).join('') + ' Basis';
|
|
2051
2055
|
out.push(dimUnderline(fitLine(header, W)));
|
|
2052
2056
|
|
|
2053
2057
|
let anyData = false;
|
|
@@ -2065,14 +2069,16 @@ export class TUI {
|
|
|
2065
2069
|
// capacity). 33.6 five-hour windows fit in 7 days — the user's own
|
|
2066
2070
|
// approximation ("from the session limits"), shipped as a ceiling, never a cap.
|
|
2067
2071
|
const t = ledger.rollingThroughput(a.name, 7);
|
|
2068
|
-
const ses = ledger.windowStats(a.name, 'ses');
|
|
2069
2072
|
const windowsPerWk = (7 * 24) / 5;
|
|
2070
2073
|
anyData = anyData || t.tokens > 0;
|
|
2071
2074
|
const vol = t.tokens > 0 ? formatTokens(t.tokens) : '--';
|
|
2072
|
-
// The ceiling needs a measured session capacity
|
|
2073
|
-
//
|
|
2074
|
-
const
|
|
2075
|
-
|
|
2075
|
+
// The ceiling needs a measured session TANK (capacity, not avg delivery) —
|
|
2076
|
+
// multiplying an old avg-delivery number understates a demand-limited account.
|
|
2077
|
+
const sesTank = this.am.capacityTank?.(i, 'ses');
|
|
2078
|
+
const ceiling = sesTank
|
|
2079
|
+
? ` · ≈${formatTokens(Math.round(windowsPerWk * sesTank.avg))}/wk ceiling`
|
|
2080
|
+
+ dim(` (${windowsPerWk.toFixed(0)} × ${formatTokens(sesTank.avg)} per 5h)`)
|
|
2081
|
+
: '';
|
|
2076
2082
|
// Always disclose the window's age boundary: today is unfinished, so the 7d
|
|
2077
2083
|
// figure grows through the day; a genuinely partial day adds the ≤-observed floor.
|
|
2078
2084
|
const note = t.partial
|
|
@@ -2083,54 +2089,61 @@ export class TUI {
|
|
|
2083
2089
|
continue;
|
|
2084
2090
|
}
|
|
2085
2091
|
const st = ledger.windowStats(a.name, win);
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
const via = est.method === 'delta'
|
|
2106
|
-
? `Δ ${(est.utilization * 100).toFixed(0)}% full` : `${(est.utilization * 100).toFixed(0)}% full`;
|
|
2107
|
-
out.push(' ' + name + ' ' + prov + ' ' + cyan(op + formatTokens(est.tokens).padStart(CW - 1))
|
|
2108
|
-
+ dim(` est from ${via}${caveat} — measured after this window completes`) + nowTag);
|
|
2109
|
-
} else {
|
|
2110
|
-
out.push(' ' + name + ' ' + prov + ' ' + dim('no completed cycle yet') + nowTag);
|
|
2111
|
-
}
|
|
2092
|
+
const tank = this.am.capacityTank?.(i, win);
|
|
2093
|
+
const nowOpen = ledger.openCycle(a.name, win);
|
|
2094
|
+
const util = this.am._windowUtilization?.(a, win);
|
|
2095
|
+
// A reading we cannot prove is from THIS window may describe the previous one —
|
|
2096
|
+
// the basis line says "unproven" instead of "live", but the number still renders:
|
|
2097
|
+
// a restored reading after a restart is real data, and suppressing it would blank
|
|
2098
|
+
// the page at exactly the moment the user opens it.
|
|
2099
|
+
const unproven = tank?.source === 'live' && tank.fresh === false;
|
|
2100
|
+
|
|
2101
|
+
// A row with NEITHER a tank nor any delivery has genuinely nothing to say. Say
|
|
2102
|
+
// WHY in the account's own terms — "no completed cycle yet" was true and useless
|
|
2103
|
+
// (reported 2026-08-25: an account sitting at 99% weekly rendered that line).
|
|
2104
|
+
if (!tank && !st && !(nowOpen?.tokensSoFar > 0)) {
|
|
2105
|
+
const why = util == null
|
|
2106
|
+
? 'no quota reading from this provider'
|
|
2107
|
+
: util > 0
|
|
2108
|
+
? `${(util * 100).toFixed(0)}% used, but no traffic through maxpool to measure with`
|
|
2109
|
+
: 'window empty — nothing used yet';
|
|
2110
|
+
out.push(' ' + name + ' ' + prov + ' ' + dim(why));
|
|
2112
2111
|
continue;
|
|
2113
2112
|
}
|
|
2114
2113
|
anyData = true;
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2114
|
+
|
|
2115
|
+
// Capacity: measured tank, or the live in-window estimate. `~` = estimate from an
|
|
2116
|
+
// open window; `≥` = we joined the window late, so the vendor's percentage counts
|
|
2117
|
+
// spend maxpool never saw and the true tank is at least this.
|
|
2118
|
+
const capCell = tank
|
|
2119
|
+
? (tank.lowerBound ? '≥' : tank.source === 'live' ? '~' : ' ') + formatTokens(tank.avg)
|
|
2120
|
+
: '--';
|
|
2121
|
+
const usedNow = nowOpen?.tokensSoFar > 0 ? formatTokens(nowOpen.tokensSoFar) : '--';
|
|
2122
|
+
const cellsByName = {
|
|
2123
|
+
Capacity: capCell,
|
|
2124
|
+
'Used now': usedNow,
|
|
2125
|
+
'Last cyc': st ? formatTokens(st.last) : '--',
|
|
2126
|
+
'Avg cyc': st ? formatTokens(st.avg10) : '--',
|
|
2127
|
+
};
|
|
2128
|
+
const cells = COLS.map(c => cellsByName[c].padStart(CW)).join('');
|
|
2129
|
+
|
|
2130
|
+
// Basis: how the capacity number was arrived at, in one short phrase. Never a
|
|
2131
|
+
// bare count — "3" told the reader nothing about what it was counting.
|
|
2132
|
+
const basis = !tank ? dim('no capacity reading yet')
|
|
2133
|
+
: tank.source === 'cycles'
|
|
2134
|
+
? dim(`${tank.n} full ${tank.n === 1 ? 'window' : 'windows'}`)
|
|
2135
|
+
: dim(`${unproven ? 'from an older reading' : 'live'} · ${((tank.utilization ?? 0) * 100).toFixed(0)}% used`);
|
|
2136
|
+
const pct = util != null && tank?.source !== 'live' ? dim(` (${(util * 100).toFixed(0)}% full now)`) : '';
|
|
2137
|
+
out.push(' ' + name + ' ' + prov + ' ' + cyan(cells) + ' ' + basis + pct);
|
|
2121
2138
|
}
|
|
2122
2139
|
|
|
2123
2140
|
out.push('');
|
|
2124
2141
|
if (!anyData) {
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
: ' A session figure appears after an account\'s 5h window resets once.'));
|
|
2131
|
-
}
|
|
2132
|
-
out.push(' ' + dim('A cycle counts only if maxpool ran for all of it and the account stayed enabled.'));
|
|
2133
|
-
out.push(' ' + dim('~ = estimated; ≥ = at least; Δ = exact-by-difference; ≈/wk = session-rate ceiling; ▸ = live this window.'));
|
|
2142
|
+
out.push(' ' + yellow('Nothing to measure yet.')
|
|
2143
|
+
+ dim(' Capacity needs traffic through maxpool plus a quota reading from the provider.'));
|
|
2144
|
+
}
|
|
2145
|
+
out.push(' ' + dim('Capacity = tokens delivered ÷ how full the provider said the window was.'));
|
|
2146
|
+
out.push(' ' + dim('~ = from the window still running · ≥ = at least this (maxpool joined the window late).'));
|
|
2134
2147
|
return out;
|
|
2135
2148
|
}
|
|
2136
2149
|
|