feat(opencode): quota pacing — burn-rate projection on the TUI sidebar#74
feat(opencode): quota pacing — burn-rate projection on the TUI sidebar#74iceteaSA wants to merge 18 commits into
Conversation
There was a problem hiding this comment.
iceteaSA has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
No issues found across 8 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant User as TUI User
participant TuiPlugin as TUI Plugin (process lifetime)
participant SidebarUI as Sidebar UI Component
participant PrefsFile as tui-preferences.jsonc
participant PrefsModule as tui-preferences.ts
participant SidebarState as sidebar-state.ts
participant NodeFS as Node.js FS
Note over TuiPlugin,SidebarUI: Startup & Preferences Loading
TuiPlugin->>PrefsModule: readTuiPreferencesFile()
PrefsModule->>NodeFS: read file from config dir/env
NodeFS-->>PrefsModule: raw JSONC text
PrefsModule->>PrefsModule: parse with jsonc-parser (tolerant)
PrefsModule-->>TuiPlugin: Record<string, unknown>
TuiPlugin->>PrefsModule: resolveAnthropicAuthPrefs(root)
PrefsModule->>PrefsModule: validate/clamp per key, fallback defaults
PrefsModule-->>TuiPlugin: AnthropicAuthTuiPrefs
TuiPlugin->>TuiPlugin: createSidebarController(prefs)
Note over TuiPlugin: createSignal for prefs & collapsed
TuiPlugin->>PrefsModule: computeEffectiveOrder(root, 'anthropic-auth', 160)
alt forceToTop=true
PrefsModule->>PrefsModule: indexOf key → FORCE_TOP_BASE + index
else manual order
PrefsModule->>PrefsModule: clamp(-10000..10000)
end
PrefsModule-->>TuiPlugin: effective order number
TuiPlugin->>PrefsModule: watchTuiPreferences(onChange)
PrefsModule->>NodeFS: fs.watch(dirname(file))
Note over PrefsModule: debounce 150ms, filter by filename
Note over SidebarUI,PrefsModule: Hot-Reload Cycle (on file edit)
User->>NodeFS: edits tui-preferences.jsonc
NodeFS-->>PrefsModule: watch event fires
PrefsModule->>PrefsModule: debounce timer
PrefsModule->>PrefsModule: re-read & re-parse (tolerant)
PrefsModule-->>TuiPlugin: new Record<string, unknown>
TuiPlugin->>PrefsModule: resolveAnthropicAuthPrefs(newRoot)
PrefsModule-->>TuiPlugin: new validated prefs
TuiPlugin->>TuiPlugin: setPrefs(newPrefs) → signal update
TuiPlugin-->>SidebarUI: signal re-renders
Note over SidebarUI,SidebarState: Quota State Polling
loop every pollMs (default 1500ms)
TuiPlugin->>SidebarState: getSidebarState()
SidebarState->>NodeFS: read state from file system
NodeFS-->>SidebarState: raw state
SidebarState-->>TuiPlugin: SidebarState
TuiPlugin-->>SidebarUI: signal update
end
Note over SidebarUI: NEW: Pacing Computation (per render)
SidebarUI->>SidebarState: computeQuotaPacing(window, FIVE_HOUR_MS, Date.now())
SidebarState->>SidebarState: validate resetsAt, elapsed guards
alt elapsed < 5 min OR elapsed < 1% of window
SidebarState-->>SidebarUI: null
else elapsed >= windowMs (stale/reset)
SidebarState-->>SidebarUI: null
else valid
SidebarState->>SidebarState: pacePercent = elapsed/windowMs * 100
SidebarState->>SidebarState: deltaPercent = used% - pacePercent
alt |delta| < 1%
SidebarState-->>SidebarUI: state='on-pace', runsOutAt=null
else delta > 0
SidebarState->>SidebarState: project runout: start + (elapsed*100)/used
alt runout < resetsAt
SidebarState-->>SidebarUI: state='deficit', runsOutAt=ISO timestamp
else
SidebarState-->>SidebarUI: state='deficit', runsOutAt=null
end
else delta < 0
SidebarState-->>SidebarUI: state='reserve', runsOutAt=null
end
end
Note over SidebarUI: Render Bar with Pacing Segments
SidebarUI->>SidebarUI: quotaBarSegments(usedPct, appearance, pacing)
alt no pacing data
SidebarUI->>SidebarUI: plain bar: filled + empty
else pacing present
alt usedCells > paceCells (deficit)
SidebarUI->>SidebarUI: fill lo, ▓ overshoot segment (err-tone), empty
else paceCells > usedCells (reserve)
SidebarUI->>SidebarUI: fill lo, ▒ headroom segment (ok-tone), empty
else equal
SidebarUI->>SidebarUI: plain bar (no change)
end
end
alt pacing state !== 'on-pace'
SidebarUI->>SidebarUI: render subline with delta % and runout
alt deficit
SidebarUI->>SidebarUI: "deficit X% · out in {formatResetIn(runsOutAt)}"
Note over SidebarUI: warn-tone text
else reserve
SidebarUI->>SidebarUI: "reserve X% · lasts"
Note over SidebarUI: muted-tone text
end
end
Note over SidebarUI: Collapsed Summary Tinting
alt any active-account window has deficit state
SidebarUI->>SidebarUI: collapsed summary turns red
else
SidebarUI->>SidebarUI: normal color
end
Note over SidebarUI,PrefsFile: Persist Collapse State
User->>SidebarUI: clicks header to collapse/expand
SidebarUI->>TuiPlugin: toggleCollapsed()
TuiPlugin->>TuiPlugin: setCollapsed(!current)
TuiPlugin->>PrefsModule: queueTuiPreferenceUpdate('anthropic-auth', ['collapsed'], newValue)
PrefsModule->>PrefsModule: read current file
PrefsModule->>PrefsModule: jsonc-parser modify (preserve comments)
PrefsModule->>NodeFS: atomic write (temp + rename)
Note over PrefsModule: serialized on promise chain
There was a problem hiding this comment.
iceteaSA has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Thanks for the pacing work. I tested the stack against current Separate product note for this PR: default-on pacing changes the collapsed quota summary color to red for an even-burn-rate deficit. That is an interpretation/projection, not actual quota exhaustion or a hard route failure. I would prefer either keeping |
Some platforms misattribute sibling-file renames to the real prefs filename, defeating the name-based pre-filter. After debounce, re-read the file and compare against last-seen content before invoking the callback. Last-seen is seeded async at watch start with a null guard to avoid races.
c66e349 to
e6325a6
Compare
There was a problem hiding this comment.
iceteaSA has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Rebased onto the updated #73 (watcher fix included underneath). Pacing tone ( Focused suites: 54/54 on the rebased stack. |
Summary
Codex-style pacing for the 5h/7d quota windows in the TUI sidebar.
sidebar-state.ts, pure + tested):computeQuotaPacing(window, windowMs, now)→deltaPercent= used % − even-burn pace % (positive = deficit, |Δ|<1 = on-pace)runsOutAt= burn-rate projection; null when the window lasts until resetresetsAt, <5 min or <1 % of window elapsed (noise), stale windows▒headroom (under pace, green) /▓overshoot (over pace, red) → empty. On-pace bars render exactly as before.reserve 12% · lasts/deficit 10% · out in 2d 7h(deficit in warn tone).sections.pacing(defaulttrue) gates segments, sublines, and the tint; hot-reloads.formatResetInis now day-aware (6d12hinstead of156h22m).Testing
computeQuotaPacingtests (reserve/deficit/on-pace, runout boundary at reset, zero-usage, noise guards, invalid input) — includes a case derived from real Codex bar valuessections.pacingresolution testsNeed help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Adds even-burn quota pacing to the TUI sidebar with run-rate projection, plus a live-reloading
tui-preferences.jsoncthat persists collapse and customizes layout, sections, and appearance. Bars show reserve/deficit segments, off-pace rows show projected runout, and the collapsed header tints warn (never red) when the active account is over pace.New Features
computeQuotaPacing(window, windowMs, now)returnspacePercent,deltaPercent,state(reserve|deficit|on-pace), andrunsOutAt | null, with noise/stale guards;formatResetInis day-aware.▒reserve,▓deficit); off-pace rows show a subline with reserve/deficit and projected “out in …”; collapsed summary uses warn tone on active-window deficit; zero-length segments are dropped; gate viasections.pacing(defaulttrue).tui-preferences.jsonc(envOPENCODE_TUI_PREFERENCES_FILEor config dirs), hot-reloads, and writes atomically while preserving comments. Persists collapse across restarts and survives slot remounts. Controls layout (forceToTop,order), behavior (startCollapsed,rememberCollapsed,pollMs,refreshDebounceMs), header (label,showVersion), sections (quota, fallbackAccounts, routing, cache, health, pacing), and appearance (barWidth, bar chars,warnThreshold,errorThreshold). Shared helpers in@cortexkit/opencode-anthropic-auth/tui-prefs:readTuiPreferencesFile,resolveAnthropicAuthPrefs,computeEffectiveOrder(honorsforceToTop),watchTuiPreferences(debounced, content-verified),queueTuiPreferenceUpdate(atomic writes).Migration
"rememberCollapsed": falseintui-preferences.jsonc.Written for commit e6325a6. Summary will update on new commits.