-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: add model rotation for automatic failover on quota/rate limits #929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
|
All contributors have signed the CLA. Thank you! ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6 issues found across 51 files
Confidence score: 3/5
- There is concrete user-impact risk:
src/agents/utils.tsnow throws ifsystemDefaultModelis omitted despite the optional TypeScript signature, which can crash existing callers. - Model rotation has functional gaps:
src/features/model-rotation/rotation-engine.tsnever records/checks token limits, so limitType="tokens" won’t rotate as expected. - Several parsing/template issues can misreport providers/status (e.g.,
src/features/model-rotation/error-parser.tsmisclassifies OpenAI rate-limit errors;src/features/builtin-commands/templates/rotation-status.tscan read wrong config paths), keeping this at moderate risk. - Pay close attention to
src/agents/utils.ts,src/features/model-rotation/rotation-engine.ts,src/features/model-rotation/error-parser.ts,src/features/builtin-commands/templates/rotation-status.ts- runtime crashes, rotation not triggering, and incorrect provider/status parsing.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/agents/utils.ts">
<violation number="1" location="src/agents/utils.ts:146">
P2: Empty model override array clears existing model (merged.model set to undefined)</violation>
<violation number="2" location="src/agents/utils.ts:167">
P2: Optional parameter now required at runtime — TypeScript signature says `systemDefaultModel` is optional but code throws when it’s missing, causing runtime crashes for callers that omit it.</violation>
</file>
<file name="src/features/builtin-commands/templates/rotation-status.ts">
<violation number="1" location="src/features/builtin-commands/templates/rotation-status.ts:22">
P2: Rotation status template hard-codes config/state paths, ignoring XDG/OPENCODE_CONFIG_DIR and Windows resolution, so it can read wrong files and misreport status.</violation>
</file>
<file name="src/features/model-rotation/rotation-engine.ts">
<violation number="1" location="src/features/model-rotation/rotation-engine.ts:33">
P2: Token-based rotation is nonfunctional: token limits are never recorded or checked, so limitType="tokens" will not trigger rotation.</violation>
</file>
<file name="src/features/model-rotation/error-parser.test.ts">
<violation number="1" location="src/features/model-rotation/error-parser.test.ts:28">
P2: Anthropic 529 error fixture is incorrect (`quota_exceeded` instead of documented `overloaded_error`), causing real Anthropic overload/quota errors to parse as unknown provider.</violation>
</file>
<file name="src/features/model-rotation/error-parser.ts">
<violation number="1" location="src/features/model-rotation/error-parser.ts:86">
P2: OpenAI rate-limit errors with `type: "rate_limit_error"` are misclassified as Anthropic because provider detection checks `errorType` before OpenAI `errorCode`.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Model rotation feature allows agents to automatically switch between multiple configured models when rate limits or quota errors are detected. Features: - Configurable rotation per agent with model pools - Error detection for rate limits, quota exceeded, overloaded errors - Usage tracking (calls or tokens) with configurable limits - Cooldown periods before model reuse - State persistence across sessions - rotation-status command to view current rotation state Schema changes: - AgentOverrideConfig.model now accepts string | string[] - Added RotationConfig schema for rotation settings - Added 'rotation-status' to BuiltinCommandNameSchema - Added 'model-rotation' to HookNameSchema
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <[email protected]>
…te limits Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <[email protected]>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <[email protected]>
|
@cubic-dev-ai re-run a review |
@TheSmuks I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3 issues found across 20 files
Confidence score: 3/5
- Model rotation has two concrete failover risks in
src/features/model-rotation/rotation-engine.ts: cooldown never reactivates depleted models and rotation can return the current model, which could leave systems stuck on an unhealthy model. - Error handling in
src/features/model-rotation/error-parser.tsmisclassifies 429 quota errors as rate limits, which could cause incorrect backoff/retry behavior for quota-exhausted users. - These are medium–high severity behavioral issues (6–7/10), so there’s some user-impacting risk despite being localized to model-rotation logic.
- Pay close attention to
src/features/model-rotation/rotation-engine.ts,src/features/model-rotation/error-parser.ts- failover rotation and quota error classification behavior.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/features/model-rotation/rotation-engine.ts">
<violation number="1" location="src/features/model-rotation/rotation-engine.ts:68">
P1: Rotation can return the current model, preventing failover and marking it depleted while still selected.</violation>
<violation number="2" location="src/features/model-rotation/rotation-engine.ts:107">
P1: Cooldown reset never triggers because depleted flag blocks reactivation, leaving models permanently unavailable.</violation>
</file>
<file name="src/features/model-rotation/error-parser.ts">
<violation number="1" location="src/features/model-rotation/error-parser.ts:32">
P2: 429 quota errors (e.g., OpenAI `insufficient_quota`) are misclassified as `rate_limit` because the 429 shortcut ignores nested quota codes/messages.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <[email protected]>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <[email protected]>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3 issues found across 21 files
Confidence score: 3/5
- There is some risk due to concrete behavior gaps in
src/agents/utils.tsand model rotation logic, so a cautious merge is warranted. - Most severe: in
src/agents/utils.ts,orchestrator-sisyphusis skipped whensystemDefaultModelis unset even if an override provides a model, which can change runtime selection behavior. - Model-rotation handling in
src/features/model-rotation/error-parser.tsandsrc/features/model-rotation/hooks.tsmay miss overload-triggered rotations and inflate usage metrics during streaming, potentially affecting resilience and reporting. - Pay close attention to
src/agents/utils.ts,src/features/model-rotation/error-parser.ts,src/features/model-rotation/hooks.ts- model selection/rotation logic and usage accounting may be impacted.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/features/model-rotation/error-parser.ts">
<violation number="1" location="src/features/model-rotation/error-parser.ts:96">
P2: Anthropic overload errors (`overloaded_error`) are detected for provider inference but not treated as rotation-triggering unless the message happens to include rotation keywords, so overload failures can be missed.</violation>
</file>
<file name="src/agents/utils.ts">
<violation number="1" location="src/agents/utils.ts:226">
P1: orchestrator-sisyphus is skipped when systemDefaultModel is unset, even if an override provides a model</violation>
</file>
<file name="src/features/model-rotation/hooks.ts">
<violation number="1" location="src/features/model-rotation/hooks.ts:123">
P2: Usage is recorded on every streaming `message.updated`, inflating call/token counts for a single assistant message.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 22 files
Confidence score: 3/5
- Round-robin rotation in
src/features/model-rotation/rotation-engine.tsalways restarts from the first model, which can bias selection and skip the next-after-current behavior users expect. - This is a user-visible behavior bug with moderate severity, so there’s some risk if merged without a fix.
- Pay close attention to
src/features/model-rotation/rotation-engine.ts- rotation logic restarts from the first model instead of advancing from the current one.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/features/model-rotation/rotation-engine.ts">
<violation number="1" location="src/features/model-rotation/rotation-engine.ts:83">
P2: Round-robin rotation is incorrect: selection always restarts from the first model, biasing earlier entries and not choosing the next after the current model.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Previously, findNextAvailableModel always iterated from the beginning of the availableModels array, biasing earlier entries. Now it starts from the model after the current one and wraps around, ensuring fair round-robin distribution (a → b → c → a → ...).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 issue found across 22 files
Confidence score: 3/5
- Cooldown expiry handling in
src/features/model-rotation/state-manager.tsdoesn’t reset usage counters, which can leave models stuck over limit and immediately re-depleted after cooldown, affecting rotation behavior. - This is a concrete user-facing logic issue, so there’s some risk despite the rest of the changes being unspecified.
- Pay close attention to
src/features/model-rotation/state-manager.ts- ensure cooldown expiry properly resets usage counters.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/features/model-rotation/state-manager.ts">
<violation number="1" location="src/features/model-rotation/state-manager.ts:82">
P2: Cooldown expiry does not reset usage counters, so models remain over limit and are immediately re-depleted after a cooldown ends.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
When a model's cooldown period expired, only the cooldown flags were being cleared but usage counters (callCount, tokenCount) remained at their previous values. This caused models to immediately re-deplete after cooldown since they were still over their limits. Now markAvailable() also resets callCount to 0 and tokenCount to undefined, allowing the model to start fresh after cooldown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No issues found across 22 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Summary
rotation-statuscommand to view current rotation stateChanges
src/features/model-rotation/module:error-parser.ts- Detects rate limit, quota, and overload errors from API responsesstate-manager.ts- Persists rotation state across sessionsrotation-engine.ts- Handles model selection and rotation logichooks.ts- Event-based rotation triggersconstants.ts- Error patterns and default configurationsrc/hooks/model-rotation/- Hook registrationsrc/config/schema.ts:AgentOverrideConfig.modelnow acceptsstring | string[]RotationConfigSchemawithenabled,limitType,limitValue,cooldownMsmodel-rotationtoHookNameSchemarotation-statustoBuiltinCommandNameSchemasrc/agents/utils.ts-normalizeModel()helper for model array handling with rotation awarenesssrc/agents/sisyphus-junior.ts- Model normalization for rotation supportsrc/agents/types.ts- Re-export types from schemarotation-statuscommand insrc/features/builtin-commands/Screenshots
N/A - Backend feature, no UI changes
Testing
bun run typecheck bun testRelated Issues
N/A
Summary by cubic
Adds automatic model rotation to fail over when rate limits, quota, or overload errors occur. Also overhauls model resolution and removes hardcoded defaults so agents use your OpenCode default model unless you set them explicitly.
New Features
Migration
Written for commit 9ba54cc. Summary will update on new commits.