@rikcodes/teamclaude 1.1.22-rik.5 → 1.1.22-rik.6

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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +2 -2
  3. package/src/tui.js +36 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rikcodes/teamclaude",
3
- "version": "1.1.22-rik.5",
3
+ "version": "1.1.22-rik.6",
4
4
  "description": "Multi-account proxy for Claude Code and Codex: pools Claude Max, ChatGPT/Codex, API-key and third-party backend accounts, and rotates on quota",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -37,7 +37,7 @@ import { ResetCreditRedeemer } from './codex-reset-credits.js';
37
37
  import { Warmer } from './warmer.js';
38
38
  import { formatWarmupScheduleConfirmation, resolveWarmupConfig } from './warmup-schedule.js';
39
39
  import { Sidecar, SIDECAR_DRAIN_GRACE_MS, SIDECAR_SHUTDOWN_GRACE_MS } from './sidecar.js';
40
- import { TUI } from './tui.js';
40
+ import { TUI, ACCOUNT_SORTS } from './tui.js';
41
41
  import { SessionTitles } from './session-titles.js';
42
42
  import { captureEarlyConsole } from './early-log.js';
43
43
  import { RemoteControl, createAttachSession } from './tui-remote.js';
@@ -535,7 +535,7 @@ async function serverCommand() {
535
535
  // Read by the server per request and by the TUI per frame, so the reload
536
536
  // is the whole application: the next request is timed, or is not.
537
537
  config.throughputMeter = diskConfig.throughputMeter === true;
538
- config.accountSort = diskConfig.accountSort === 'weekly-reset' ? 'weekly-reset' : 'arranged';
538
+ config.accountSort = ACCOUNT_SORTS.includes(diskConfig.accountSort) ? diskConfig.accountSort : 'arranged';
539
539
  // Read by `run`/`env` from disk, but the TUI settings screen shows it live.
540
540
  config.defaultClientMode = diskConfig.defaultClientMode === 'base-url' ? 'base-url' : 'mitm';
541
541
  // The fleet switch for spending Codex reset credits. The redeemer reads it
package/src/tui.js CHANGED
@@ -287,21 +287,36 @@ const PANE_MIN = 62;
287
287
  const listRank = (/** @type {any} */ a) => (Number.isFinite(a?.displayOrder) ? a.displayOrder : Infinity);
288
288
 
289
289
  // How the account list is ordered inside each provider group (`accountSort`).
290
- // `arranged` is the operator's own order (listRank); `weekly-reset` puts the
291
- // account whose weekly window ends soonest first, so quota that is about to
290
+ // `arranged` is the operator's own order (listRank). Each of the others puts
291
+ // the account whose window ends soonest first, so quota that is about to
292
292
  // expire unspent is at the top of the list.
293
- const ACCOUNT_SORTS = ['arranged', 'weekly-reset'];
293
+ //
294
+ // The window each sort reads. S7 and F7 are the family's own weekly bucket
295
+ // where the account has one, else the all-models weekly, which is what governs
296
+ // that family on such an account — the rule quota-summary.js resolves a
297
+ // family's window by.
298
+ /** @type {Record<string, (q: any) => any>} */
299
+ const SORT_RESET = {
300
+ 'session-reset': q => q.unified5hReset,
301
+ 'weekly-reset': q => q.unified7dReset,
302
+ 'sonnet-reset': q => (q.unified7dSonnet != null ? q.unified7dSonnetReset : q.unified7dReset),
303
+ 'fable-reset': q => (q.unified7dFable != null ? q.unified7dFableReset : q.unified7dReset),
304
+ };
305
+ export const ACCOUNT_SORTS = ['arranged', ...Object.keys(SORT_RESET)];
294
306
  /** @type {Record<string, string>} */
295
- const ACCOUNT_SORT_LABELS = { arranged: 'arranged', 'weekly-reset': 'weekly reset' };
307
+ const ACCOUNT_SORT_LABELS = {
308
+ arranged: 'arranged',
309
+ 'session-reset': 'session reset',
310
+ 'weekly-reset': 'weekly reset',
311
+ 'sonnet-reset': 'S7 reset',
312
+ 'fable-reset': 'F7 reset',
313
+ };
296
314
 
297
- // When the account's weekly window resets — the sort key behind `weekly-reset`.
298
- // No reading (an API-key account, or one that has not reported) and a reset
315
+ // The sort key: when the window resets. No reading (an API-key account, one
316
+ // that has not reported, a five-hour window nothing has opened) and a reset
299
317
  // that has already passed both sort last: the second is a window that has just
300
318
  // started over, so its next reset is the one furthest away.
301
- const weeklyResetRank = (/** @type {any} */ a, /** @type {number} */ now) => {
302
- const t = a?.quota?.unified7dReset;
303
- return Number.isFinite(t) && t > now ? t : Infinity;
304
- };
319
+ const resetRank = (/** @type {any} */ t, /** @type {number} */ now) => (Number.isFinite(t) && t > now ? t : Infinity);
305
320
 
306
321
  // How long a reorder waits after the last move before it is written. Longer
307
322
  // than a terminal's key-repeat interval, so a held arrow is one write; short
@@ -3034,16 +3049,16 @@ export class TUI {
3034
3049
  * Which is also why the arrangement is a sort key rather than a permutation
3035
3050
  * of `am.accounts`: see _doMoveAccount.
3036
3051
  *
3037
- * With `accountSort: "weekly-reset"` the soonest weekly reset goes before
3038
- * the arrangement, which then only breaks ties. Not on the reorder screen,
3039
- * and not when `arranged` is asked for: the arrangement is what that screen
3052
+ * With a reset sort (`accountSort`) the soonest reset goes before the
3053
+ * arrangement, which then only breaks ties. Not on the reorder screen, and
3054
+ * not when `arranged` is asked for: the arrangement is what that screen
3040
3055
  * edits, so it must see that order.
3041
3056
  *
3042
3057
  * @param {{ arranged?: boolean }} [opts]
3043
3058
  */
3044
3059
  _displayOrder({ arranged = false } = {}) {
3045
- const byReset = !arranged && this.config?.accountSort === 'weekly-reset'
3046
- && !(this.mode === 'select' && this.selAction === 'reorder');
3060
+ const resetOf = arranged || (this.mode === 'select' && this.selAction === 'reorder')
3061
+ ? null : SORT_RESET[this._accountSort()];
3047
3062
  const now = Date.now();
3048
3063
  return this.am.accounts
3049
3064
  .map((/** @type {any} */ _, /** @type {number} */ i) => i)
@@ -3054,9 +3069,9 @@ export class TUI {
3054
3069
  // Provider, then the sort, then the arrangement: the provider is what a
3055
3070
  // row IS, so no sort and no number the operator set crosses it.
3056
3071
  if (px !== py) return px - py;
3057
- if (byReset) {
3058
- const tx = weeklyResetRank(this.am.accounts[x], now);
3059
- const ty = weeklyResetRank(this.am.accounts[y], now);
3072
+ if (resetOf) {
3073
+ const tx = resetRank(resetOf(this.am.accounts[x].quota || {}), now);
3074
+ const ty = resetRank(resetOf(this.am.accounts[y].quota || {}), now);
3060
3075
  if (tx !== ty) return tx < ty ? -1 : 1; // Infinity - Infinity is NaN, so compare
3061
3076
  }
3062
3077
  const rx = listRank(this.am.accounts[x]);
@@ -3695,8 +3710,9 @@ export class TUI {
3695
3710
  if (byId('orderAccounts')) lines.push(row(byId('orderAccounts')));
3696
3711
  if (byId('accountSort')) {
3697
3712
  lines.push(row(byId('accountSort')));
3698
- lines.push(dim(' Weekly reset lists the account whose week ends soonest first;'));
3699
- lines.push(dim(' the arranged order breaks ties.'));
3713
+ lines.push(dim(' A reset sort lists the account whose window ends soonest first;'));
3714
+ lines.push(dim(' S7/F7 read the weekly window on an account without one. The'));
3715
+ lines.push(dim(' arranged order breaks ties.'));
3700
3716
  }
3701
3717
  lines.push('');
3702
3718
  // ── Network