refactor: extract forecast command#158
refactor: extract forecast command#158ndycode wants to merge 2 commits intorefactor/pr1-remove-inline-switch-wrapperfrom
Conversation
|
Important Review skippedAuto reviews are limited based on label configuration. 🚫 Review skipped — only excluded labels are configured. (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Summary
codex auth forecastimplementation into a dedicated command moduleWhat Changed
lib/codex-manager/commands/forecast.tsfor forecast argument parsing, live-probe orchestration, JSON output, and display renderinglib/codex-manager.tssorunForecast(...)delegates to the extracted forecast command module through injected helpers and servicestest/codex-manager-forecast-command.test.tsfor help, invalid-option, and JSON-output coverageValidation
npm run test -- test/codex-manager-forecast-command.test.ts test/codex-manager-cli.test.tsnpm run lintnpm run typechecknpm run buildRisk and Rollback
cae16c2to restore the inline forecast implementationAdditional Notes
note: greptile review for oc-chatgpt-multi-auth. cite files like
lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.Greptile Summary
this pr extracts the
codex auth forecastimplementation from the monolithiccodex-manager.tsintolib/codex-manager/commands/forecast.ts, consistent with the ongoing command-split refactor train. the delegation inrunForecastis a clean passthrough and all injected helpers map 1-to-1 to the original call sites, so behavioral parity is preserved. the duplicateif (!arg) continue;guard from the original parser is also quietly fixed in the extracted version.key points:
formatQuotaSnapshotLineis a required dep forserializeForecastResultsbut is absent from the exportedForecastCommandDepsinterface — it's bolted on as an intersection type at therunForecastCommandcall site, which makes the public contract incomplete for any future implementorsawaitinsidefor), meaning N-account runs are O(N) latency; the module's own concurrency test confirms no shared state exists, so aPromise.allSettledrefactor would be safe and aligns with the existingparallel-probe.tspattern--livenon-JSON display path (quota-detail inline rows) and theprobeErrorsrendering branch; given the 80% project-wide coverage threshold these should be addedsaveQuotaCache/loadQuotaCacheremain injected deps, so EBUSY/EPERM retry responsibility stays with the caller as before; access tokens are scoped locally and not loggedConfidence Score: 4/5
ForecastCommandDepsinterface contract and the missing vitest coverage on the live-display and probe-error branches, both of which are straightforward to fix before or after mergeformatQuotaSnapshotLineinterface gap and sequential probe loop; test/codex-manager-forecast-command.test.ts — missing coverage for live non-JSON display and probeErrors pathsImportant Files Changed
formatQuotaSnapshotLineis missing from the exportedForecastCommandDepsinterface and the probe loop remains sequentialrunForecastbody with a singlerunForecastCommand(args, { ...deps })call; no behavioral change, all injected helpers match the original call sites exactlyprobeErrorsrendering branchSequence Diagram
sequenceDiagram participant CLI as codex-manager.ts<br/>runForecast() participant CMD as forecast.ts<br/>runForecastCommand() participant Store as loadAccounts / setStoragePath participant Cache as loadQuotaCache / saveQuotaCache participant Refresh as queuedRefresh participant Probe as fetchCodexQuotaSnapshot participant Out as logInfo / logError CLI->>CMD: runForecastCommand(args, deps) CMD->>CMD: parseForecastArgs(args) alt --help CMD->>Out: printForecastUsage() CMD-->>CLI: return 0 else parse error CMD->>Out: logError(message) CMD-->>CLI: return 1 end CMD->>Store: setStoragePath(null) CMD->>Store: loadAccounts() Store-->>CMD: AccountStorageV3 opt --live CMD->>Cache: loadQuotaCache() Cache-->>CMD: QuotaCacheData end loop each account (sequential) opt token expired CMD->>Refresh: queuedRefresh(refreshToken) Refresh-->>CMD: TokenResult end CMD->>Probe: fetchCodexQuotaSnapshot(...) Probe-->>CMD: CodexQuotaSnapshot CMD->>Cache: updateQuotaCacheForAccount(...) end CMD->>CMD: evaluateForecastAccounts / summarizeForecast / recommendForecastAccount alt --json CMD->>Cache: saveQuotaCache (if changed) CMD->>Out: logInfo(JSON.stringify(...)) else display CMD->>Out: render per-account rows + recommendation CMD->>Cache: saveQuotaCache (if changed) end CMD-->>CLI: return 0Comments Outside Diff (2)
lib/codex-manager/commands/forecast.ts, line 637-645 (link)deps_formatQuotaSnapshotLineis assigned at the top of everyrunForecastCommandcall, then used later insideserializeForecastResultswhich is only invoked after severalawaitpoints. in a concurrent scenario (e.g. two overlapping calls from integration tests, a future parallel-probe path, or the existingcodex-manager-cli.test.tssuite running cases in the same process), the second call overwrites the module-level variable while the first is suspended at anawait, soserializeForecastResultspicks up the wrongformatQuotaSnapshotLinedep.serializeForecastResultsshould receive the formatter as a direct argument instead:then pass
deps.formatQuotaSnapshotLineat the call-site and drop the module-level variable entirely.Prompt To Fix With AI
lib/codex-manager/commands/forecast.ts, line 830-832 (link)joinStyledSegmentssilently replaced with different join behaviorthe original inline implementation called
joinStyledSegments(rowParts)(a dedicated ANSI-aware helper), then emitted the leading styled|separately. the new code removesjoinStyledSegmentsfrom deps entirely and substitutesrowParts.join(deps.stylePromptText(" | ", "muted")). ifjoinStyledSegmentsjoined with a plain space, or applied ANSI resets between segments, the rendered row will differ in terminal output. this is a silent behavior change that isn't covered by any of the new tests — they mockstylePromptTextas an identity function so the difference would never surface.either add
joinStyledSegmentstoForecastCommandDepsand pass it through, or add a test that captures the full rendered row string so the exact separator can be verified.Prompt To Fix With AI
Prompt To Fix All With AI
Last reviewed commit: "fix: isolate forecas..."