feat(api): add OpenAI-compatible credential pool failover - #1706
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (11)src/**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
{src/services/**/*.ts,src/utils/**/*.ts}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{ts,tsx,js,jsx,py,json,md}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*.{ts,tsx,js,jsx,py}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*⚙️ CodeRabbit configuration file
Files:
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}⚙️ CodeRabbit configuration file
Files:
**⚙️ CodeRabbit configuration file
Files:
**/*.test.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*.test.{ts,tsx,js}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}⚙️ CodeRabbit configuration file
Files:
🔇 Additional comments (2)
📝 WalkthroughWalkthroughImplements ChangesOPENAI_API_KEYS credential pool rotation
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/services/api/openaiShim.ts (1)
2820-2868:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTreat whitespace-only
OPENAI_API_KEYas unset before xAI OAuth fallback.
openAIApiKeyis trimmed, but the xAI OAuth gate and final fallback still use rawprocess.env.OPENAI_API_KEY. If the env is set to spaces, OAuth fallback is skipped and an invalid auth value can be sent.Suggested fix
- const xaiOAuthToken = + const xaiOAuthToken = isXaiRoute && !this.providerOverride?.apiKey && !routeCredential && !openAIApiKeysPoolRaw && - !process.env.OPENAI_API_KEY + !openAIApiKey ? await resolveXaiAccessToken() : undefined @@ const apiKeyRaw = this.providerOverride?.apiKey ?? (routeCredentialIsGenericOpenAIFallback ? undefined : routeCredential) ?? openAIApiKeysPoolRaw ?? routeCredential ?? - process.env.OPENAI_API_KEY ?? - xaiOAuthToken ?? - '' + openAIApiKey || + xaiOAuthToken || + ''🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/services/api/openaiShim.ts` around lines 2820 - 2868, The xAI OAuth fallback gate and the final apiKeyRaw assignment are using the raw process.env.OPENAI_API_KEY without trimming, while the openAIApiKey variable is trimmed. If the environment variable contains only whitespace, it will be treated as set and prevent the OAuth fallback, then pass an invalid whitespace-only value. Replace the raw process.env.OPENAI_API_KEY references with the trimmed openAIApiKey variable in two places: the xAI condition check (change !process.env.OPENAI_API_KEY to !openAIApiKey) and in the apiKeyRaw fallback chain (change the last process.env.OPENAI_API_KEY to openAIApiKey).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/services/api/openaiShim.test.ts`:
- Around line 2621-2725: Add a new test following the existing pattern to verify
that comma-separated values in the singular OPENAI_API_KEY environment variable
support key rotation on failure. Create a test that sets
OPENAI_API_KEY='key-a,key-b' without setting OPENAI_API_KEYS, mocks
globalThis.fetch to return a 429 or 401 error on the first request, and asserts
that the Authorization header or api-key header rotates to the next key on the
second request, similar to the existing tests like 'OPENAI_API_KEYS rotates to
the next key on rate-limit failure' and 'OPENAI_API_KEYS rotates Azure api-key
auth on auth failure'.
---
Outside diff comments:
In `@src/services/api/openaiShim.ts`:
- Around line 2820-2868: The xAI OAuth fallback gate and the final apiKeyRaw
assignment are using the raw process.env.OPENAI_API_KEY without trimming, while
the openAIApiKey variable is trimmed. If the environment variable contains only
whitespace, it will be treated as set and prevent the OAuth fallback, then pass
an invalid whitespace-only value. Replace the raw process.env.OPENAI_API_KEY
references with the trimmed openAIApiKey variable in two places: the xAI
condition check (change !process.env.OPENAI_API_KEY to !openAIApiKey) and in the
apiKeyRaw fallback chain (change the last process.env.OPENAI_API_KEY to
openAIApiKey).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 524b5196-62af-4aa5-a321-1671da86a371
📒 Files selected for processing (6)
.env.exampledocs/advanced-setup.mdsrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
docs/advanced-setup.mdsrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
docs/advanced-setup.mdsrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
docs/advanced-setup.mdsrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
🔇 Additional comments (6)
src/services/api/credentialPool.ts (1)
1-104: LGTM!src/services/api/credentialPool.test.ts (1)
1-42: LGTM!src/services/api/openaiShim.ts (1)
14-14: LGTM!Also applies to: 99-108, 2174-2197, 2798-2819, 2869-3328
src/services/api/openaiShim.test.ts (1)
15-15: LGTM!Also applies to: 154-154, 195-195, 2561-2590
.env.example (1)
178-179: LGTM!docs/advanced-setup.md (1)
327-328: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/integrations/routeMetadata.test.ts`:
- Around line 35-61: The test suite for getRouteCredentialEnvVars validates
descriptor-backed routes like openrouter, deepseek, and others, but does not
include a test case for the custom route type despite explicit custom handling
being added to the implementation. Add a new expect assertion for
getRouteCredentialEnvVars('custom') following the same pattern as the existing
assertions (openrouter, deepseek, hicap, venice, xiaomi-mimo), and ensure it
validates that the returned credential env vars array includes the correct keys
with OPENAI_API_KEYS in the proper precedence order as implemented in the
routeMetadata.ts custom branch.
In `@src/services/api/credentialPool.test.ts`:
- Around line 30-41: Add a new test case to credentialPool.test.ts that
exercises the all-credentials-cooling-down fallback branch in the
CredentialPool.next() method. Create a test that initializes a CredentialPool
with multiple credentials, reports failures with cooldown for all of them
(ensuring they all have different failure timestamps), and then calls
pool.next() while they are all still in their cooldown periods. Verify that the
method returns the credential with the least-recent failure time as the fallback
choice, which exercises the fallback logic at lines 50-69 in credentialPool.ts.
In `@src/utils/providerValidation.ts`:
- Around line 122-124: The hasOpenAICredential function currently returns true
for delimiter-only strings like ", ," because it only checks if
getRouteCredentialValue returns a truthy value without validating that actual
tokens exist. Modify the function to not only retrieve the credential value but
also validate that when split by delimiters, it contains at least one non-empty
token. This ensures that validation fails for strings containing only delimiters
and passes only when actual usable credential tokens are present.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 62989187-0800-4b68-a656-fca0e4999027
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (11)
.env.exampledocs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (17)
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
docs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
docs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
docs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/integrations/routeMetadata.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/routeMetadata.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerValidation.test.tssrc/utils/providerValidation.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
🔇 Additional comments (13)
.env.example (1)
178-179: LGTM!docs/advanced-setup.md (1)
327-328: LGTM!src/services/api/openaiShim.test.ts (6)
2655-2687: Past review comment addressed.This test covers the comma-separated
OPENAI_API_KEYrotation path that was previously missing.
15-15: LGTM!Also applies to: 154-154, 195-195
2561-2589: LGTM!
2621-2653: LGTM!
2689-2726: LGTM!
2728-2759: LGTM!src/services/api/openaiShim.ts (1)
99-108: LGTM!Also applies to: 2174-2197, 2798-2975, 3087-3100, 3184-3189, 3226-3226, 3311-3332
src/services/api/credentialPool.ts (1)
1-104: LGTM!src/integrations/routeMetadata.ts (1)
585-605: LGTM!src/integrations/vendors/openai.ts (1)
9-34: LGTM!src/utils/providerValidation.test.ts (1)
15-16: LGTM!Also applies to: 311-318
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/integrations/vendors/openai.ts`:
- Around line 9-13: The requiredEnvVars and credentialEnvVars arrays now accept
both OPENAI_API_KEYS and OPENAI_API_KEY environment variables, but the
missing-credential error messaging only tells users about OPENAI_API_KEY. Update
the error/guidance message that displays when credentials are missing to inform
users that either OPENAI_API_KEYS or OPENAI_API_KEY can be used, ensuring the
runtime messaging is consistent with the accepted environment variables across
all related message strings at the referenced line ranges.
In `@src/utils/providerValidation.ts`:
- Around line 138-141: The hasOpenAICredential function only validates the
credential from getRouteCredentialValue('openai', env) and ignores the
OPENAI_API_KEY fallback. When OPENAI_API_KEYS contains only delimiters (like ",
,"), the function returns false even if OPENAI_API_KEY is valid. Fix this by
modifying hasOpenAICredential to check both the route credential value AND the
direct OPENAI_API_KEY environment variable, returning true if either source
contains a valid non-empty credential. Additionally, add a regression test case
that verifies the validation passes when OPENAI_API_KEYS is set to
delimiter-only values but OPENAI_API_KEY contains a valid API key.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 10db722d-af57-4400-b6c1-c42c8a43a62c
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (11)
.env.exampledocs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (17)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tsdocs/advanced-setup.mdsrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/openaiShim.test.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerValidation.test.tssrc/utils/providerValidation.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tsdocs/advanced-setup.mdsrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/openaiShim.test.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tsdocs/advanced-setup.mdsrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
🔇 Additional comments (13)
src/services/api/openaiShim.test.ts (6)
15-15: LGTM!Also applies to: 154-154, 195-195
2561-2590: LGTM!
2621-2653: LGTM!
2655-2687: LGTM!
2689-2726: LGTM!
2728-2759: LGTM!src/services/api/credentialPool.ts (1)
1-104: LGTM!src/services/api/credentialPool.test.ts (1)
1-55: LGTM!src/services/api/openaiShim.ts (1)
14-14: LGTM!Also applies to: 99-108, 2174-2197, 2798-3332
.env.example (1)
178-179: LGTM!docs/advanced-setup.md (1)
327-328: LGTM!src/integrations/routeMetadata.ts (1)
585-585: LGTM!Also applies to: 598-605
src/integrations/routeMetadata.test.ts (1)
10-10: LGTM!Also applies to: 35-39, 42-43, 47-48, 52-53, 57-58, 62-63, 97-113
18d09f5 to
6693d93
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/services/api/openaiShim.test.ts`:
- Around line 2621-2759: Add a new regression test after the existing
"OPENAI_API_KEYS rotates Azure api-key auth on auth failure" test that verifies
the behavior when all pooled keys are 401-disabled. The test should set up
multiple API keys using OPENAI_API_KEYS environment variable, configure the mock
fetch to return 401 status for the first requests until all keys have been
tried, then make a second client request and verify that the subsequent request
does not attempt to reuse a key that was previously disabled by a 401 response.
This test should follow the same pattern as the existing tests in this file,
using an authorizations or apiKeys array to capture headers across multiple
fetch calls and verify the expected key rotation sequence.
In `@src/services/api/openaiShim.ts`:
- Around line 2820-2827: The OPENAI_API_KEY environment variable is being
trimmed and used directly without validating whether it contains actual usable
content, allowing delimiter-only or whitespace-only strings to be treated as
valid credentials. This blocks fallback authentication paths like xAI OAuth. Add
a validation check after trimming OPENAI_API_KEY to ensure it is not just an
empty string or contains only delimiters before treating it as a valid
credential in the xaiOAuthToken conditional logic at line 2820 and in the
similar code block at lines 2867-2872.
- Around line 2912-2921: The authValue assignment in the buildHeadersForAttempt
function falls back to singleAuthValue when credentialLease is null, which
causes disabled keys to be reused. Remove the fallback to singleAuthValue from
the authValue assignment expression in buildHeadersForAttempt so that when
credentialLease is null (indicating the pool cannot lease a credential), the
code does not fall back to the pre-computed singleAuthValue which may be a
disabled key. Apply the same fix at the two other locations mentioned (lines
3184-3185) where this pattern appears.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2ddf7eec-3cc8-4862-a752-3001cf91f014
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (11)
.env.exampledocs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (17)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.ts
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/openaiShim.test.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerValidation.test.tssrc/utils/providerValidation.ts
🔇 Additional comments (9)
src/services/api/credentialPool.ts (1)
1-104: LGTM!src/services/api/credentialPool.test.ts (1)
1-56: LGTM!.env.example (1)
178-179: LGTM!src/integrations/routeMetadata.ts (1)
199-205: LGTM!Also applies to: 208-221, 600-620
src/integrations/vendors/openai.ts (1)
9-13: LGTM!Also applies to: 25-25, 33-33, 36-36
src/integrations/routeMetadata.test.ts (1)
10-10: LGTM!Also applies to: 36-39, 42-42, 47-47, 52-52, 57-57, 62-62, 97-123
src/utils/providerValidation.ts (1)
109-109: LGTM!Also applies to: 122-143, 316-318, 551-551, 570-570
src/utils/providerValidation.test.ts (1)
15-15: LGTM!Also applies to: 134-134, 307-340, 499-499, 534-534
docs/advanced-setup.md (1)
327-328: LGTM!
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/integrations/vendors/openai.ts (1)
33-43:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd placeholder validation for
OPENAI_API_KEYSto match the new accepted credential sources.Line [33] accepts
OPENAI_API_KEYS, but Line [39]-Line [43] only rejects placeholderSUA_CHAVEforOPENAI_API_KEY. This letsOPENAI_API_KEYS=SUA_CHAVEpass startup validation and fail later at runtime.Suggested patch
invalidCredentialValues: [ + { + envVar: 'OPENAI_API_KEYS', + value: 'SUA_CHAVE', + message: + 'Invalid OPENAI_API_KEYS: placeholder value SUA_CHAVE detected. Set real key(s) or unset for local providers.', + }, { envVar: 'OPENAI_API_KEY', value: 'SUA_CHAVE', message: 'Invalid OPENAI_API_KEY: placeholder value SUA_CHAVE detected. Set a real key or unset for local providers.', }, ],🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/integrations/vendors/openai.ts` around lines 33 - 43, The invalidCredentialValues array in the openai.ts file only validates the placeholder value 'SUA_CHAVE' for the 'OPENAI_API_KEY' environment variable, but the credentialEnvVars array accepts both 'OPENAI_API_KEYS' (plural) and 'OPENAI_API_KEY'. Add another validation entry to the invalidCredentialValues array that checks for the same 'SUA_CHAVE' placeholder value but for the 'OPENAI_API_KEYS' environment variable to ensure both credential sources are properly validated and prevent invalid placeholders from passing startup validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/integrations/vendors/openai.ts`:
- Around line 33-43: The invalidCredentialValues array in the openai.ts file
only validates the placeholder value 'SUA_CHAVE' for the 'OPENAI_API_KEY'
environment variable, but the credentialEnvVars array accepts both
'OPENAI_API_KEYS' (plural) and 'OPENAI_API_KEY'. Add another validation entry to
the invalidCredentialValues array that checks for the same 'SUA_CHAVE'
placeholder value but for the 'OPENAI_API_KEYS' environment variable to ensure
both credential sources are properly validated and prevent invalid placeholders
from passing startup validation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2e3a7b19-4d5a-4170-9abe-e49fb9257874
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (12)
.env.exampledocs/advanced-setup.mdscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (18)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.ts
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/services/api/credentialPool.test.tssrc/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
scripts/system-check.test.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerValidation.tssrc/utils/providerValidation.test.ts
🔇 Additional comments (14)
src/services/api/credentialPool.ts (1)
1-104: LGTM!src/services/api/credentialPool.test.ts (1)
1-56: LGTM!src/services/api/openaiShim.ts (4)
2816-2828: Duplicate:OPENAI_API_KEYvalidation gap still present.The previous review flagged that
openAIApiKey = process.env.OPENAI_API_KEY?.trim()treats delimiter-only values (e.g.,",") as present, blocking xAI OAuth fallback. TheopenAIApiKeysPoolRawnow validates viaparseCredentialList, butopenAIApiKeydoes not. This was flagged in the prior round and the suggested fix was not applied.
2909-2921: Duplicate:singleAuthValuefallback reuses disabled credentials.The previous review flagged that when all pooled keys are 401-disabled,
credentialPool.next()returnsnull, butauthValuefalls back tosingleAuthValue(the first parsed credential, now disabled). The suggested fix to conditionally suppress this fallback when a pool is active was not applied.
14-14: LGTM!Also applies to: 99-108, 2170-2197
2798-2803: LGTM!Also applies to: 2866-2884, 2922-2975, 3087-3100, 3183-3189, 3225-3226, 3311-3332
src/services/api/openaiShim.test.ts (3)
2621-2759: Duplicate: Missing regression test for exhausted credential pool.The previous review requested a test for the case where all pooled keys are 401-disabled and a subsequent request is made. This verifies that disabled keys aren't reused (tied to the
singleAuthValuefallback issue in the implementation). That test was not added.
15-15: LGTM!Also applies to: 154-154, 195-195
2561-2589: LGTM!src/integrations/routeMetadata.ts (1)
194-221: LGTM!Also applies to: 596-624
src/integrations/routeMetadata.test.ts (1)
35-65: LGTM!Also applies to: 97-123
src/utils/providerValidation.ts (1)
104-113: LGTM!Also applies to: 122-143, 316-318, 551-573
src/utils/providerValidation.test.ts (1)
15-15: LGTM!Also applies to: 311-341
scripts/system-check.test.ts (1)
26-27: LGTM!Also applies to: 187-219
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/integrations/vendors/openai.ts (1)
33-43:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd placeholder-value validation parity for
OPENAI_API_KEYS.
invalidCredentialValuesonly guardsOPENAI_API_KEY. With this change,OPENAI_API_KEYS=SUA_CHAVEbypasses the placeholder check and can pass validation despite being an obvious invalid credential value.Suggested fix
invalidCredentialValues: [ { envVar: 'OPENAI_API_KEY', value: 'SUA_CHAVE', message: 'Invalid OPENAI_API_KEY: placeholder value SUA_CHAVE detected. Set a real key or unset for local providers.', }, + { + envVar: 'OPENAI_API_KEYS', + value: 'SUA_CHAVE', + message: + 'Invalid OPENAI_API_KEYS: placeholder value SUA_CHAVE detected. Set real comma-separated keys or unset for local providers.', + }, ],🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/integrations/vendors/openai.ts` around lines 33 - 43, The invalidCredentialValues array currently only validates OPENAI_API_KEY for the placeholder value SUA_CHAVE, but OPENAI_API_KEYS is also listed in credentialEnvVars array without corresponding placeholder validation. Add a new entry to the invalidCredentialValues array to validate OPENAI_API_KEYS with the same placeholder value SUA_CHAVE and appropriate error message, ensuring both credential environment variables have parity in their validation checks.
♻️ Duplicate comments (1)
src/services/api/openaiShim.ts (1)
3189-3196:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFail fast when the credential pool is exhausted.
When
credentialPool.next()returnsnull(all pooled keys disabled), the loop still performs outbound requests with no auth and retries untilmaxAttempts. This turns a deterministic failure into repeated external calls with user payload.Suggested fix
for (let attempt = 0; attempt < maxAttempts; attempt++) { const credentialLease = credentialPool?.next() ?? null + if (credentialPool && credentialPool.size > 0 && !credentialLease) { + throw APIError.generate( + 401, + undefined, + 'All pooled credentials were exhausted after authentication failures.', + new Headers(), + ) + } const headers = await buildHeadersForAttempt(credentialLease) try { response = await fetchWithProxyRetry( requestUrl, buildFetchInit(headers),As per coding guidelines, “Review provider routing, model selection, env precedence, auth/token handling, ... and outbound HTTP behavior with high scrutiny. Block on ... credential reuse mistakes ...”.
Also applies to: 3325-3337
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/services/api/openaiShim.ts` around lines 3189 - 3196, When credentialPool.next() returns null (indicating the credential pool is exhausted), the code currently continues to make outbound requests with no authentication across all maxAttempts retry iterations. Add an early exit condition immediately after assigning credentialLease in the loop that checks if credentialLease is null, and if so, break from the retry loop or throw an error to fail fast. This prevents unnecessary external requests and retries when no valid credentials are available. Apply this same fix at both locations mentioned (the primary occurrence and the secondary occurrence around lines 3325-3337).Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/integrations/vendors/openai.ts`:
- Around line 33-43: The invalidCredentialValues array currently only validates
OPENAI_API_KEY for the placeholder value SUA_CHAVE, but OPENAI_API_KEYS is also
listed in credentialEnvVars array without corresponding placeholder validation.
Add a new entry to the invalidCredentialValues array to validate OPENAI_API_KEYS
with the same placeholder value SUA_CHAVE and appropriate error message,
ensuring both credential environment variables have parity in their validation
checks.
---
Duplicate comments:
In `@src/services/api/openaiShim.ts`:
- Around line 3189-3196: When credentialPool.next() returns null (indicating the
credential pool is exhausted), the code currently continues to make outbound
requests with no authentication across all maxAttempts retry iterations. Add an
early exit condition immediately after assigning credentialLease in the loop
that checks if credentialLease is null, and if so, break from the retry loop or
throw an error to fail fast. This prevents unnecessary external requests and
retries when no valid credentials are available. Apply this same fix at both
locations mentioned (the primary occurrence and the secondary occurrence around
lines 3325-3337).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0a7ae337-b4cc-4b65-b73a-d69501e2dbf7
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (12)
.env.exampledocs/advanced-setup.mdscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (18)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.ts
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/integrations/vendors/openai.tsscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/integrations/vendors/openai.tsscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
src/integrations/vendors/openai.tsdocs/advanced-setup.mdscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
scripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
scripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
scripts/system-check.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
scripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerValidation.test.tssrc/utils/providerValidation.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
🔇 Additional comments (4)
src/utils/providerValidation.test.ts (1)
15-15: LGTM!Also applies to: 134-134, 307-340, 499-499, 534-534
scripts/system-check.test.ts (1)
26-26: LGTM!Also applies to: 187-219
.env.example (1)
178-179: LGTM!docs/advanced-setup.md (1)
327-328: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/advanced-setup.md`:
- Around line 327-328: The table description for `OPENAI_API_KEY` in the
advanced-setup.md file is unclear about the requiredness when `OPENAI_API_KEYS`
is also available. Update the `OPENAI_API_KEY` row to clarify that it is
required for OpenAI-compatible cloud routes only if `OPENAI_API_KEYS` is not
configured, since `OPENAI_API_KEYS` takes precedence and can serve as an
alternative. Additionally, update the `OPENAI_API_KEYS` row to explicitly state
that it can be used as an alternative to `OPENAI_API_KEY` for satisfying the
OpenAI-compatible cloud route requirement, making it clear that at least one of
these two variables is needed (except for local models).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 27c16de6-f58a-4dba-b2a1-c43361b0fe15
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (12)
.env.exampledocs/advanced-setup.mdscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (18)
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
scripts/system-check.test.tsdocs/advanced-setup.mdsrc/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
scripts/system-check.test.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
scripts/system-check.test.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
scripts/system-check.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
scripts/system-check.test.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
scripts/system-check.test.tsdocs/advanced-setup.mdsrc/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
scripts/system-check.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
scripts/system-check.test.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
scripts/system-check.test.tsdocs/advanced-setup.mdsrc/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/vendors/openai.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/vendors/openai.tssrc/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.tssrc/services/api/credentialPool.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/services/api/credentialPool.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerValidation.test.tssrc/utils/providerValidation.ts
🔇 Additional comments (11)
src/services/api/credentialPool.ts (1)
1-105: LGTM!src/services/api/credentialPool.test.ts (1)
1-56: LGTM!src/integrations/routeMetadata.ts (1)
199-221: LGTM!Also applies to: 600-620
src/integrations/routeMetadata.test.ts (1)
10-10: LGTM!Also applies to: 36-39, 42-43, 47-48, 52-53, 57-58, 62-63, 97-123
src/utils/providerValidation.ts (1)
109-109: LGTM!Also applies to: 122-143, 301-303, 318-320, 553-553, 572-572
src/integrations/vendors/openai.ts (1)
9-9: LGTM!Also applies to: 13-13, 25-25, 33-33, 36-36, 38-43
src/utils/providerValidation.test.ts (1)
15-15: LGTM!Also applies to: 134-134, 307-353, 511-511, 546-546
scripts/system-check.test.ts (1)
26-26: LGTM!Also applies to: 187-219
src/services/api/openaiShim.ts (1)
14-14: LGTM!Also applies to: 99-108, 2174-2197, 2798-2803, 2816-2876, 2886-2888, 2913-2981, 3093-3106, 3190-3339
src/services/api/openaiShim.test.ts (1)
15-15: LGTM!Also applies to: 154-154, 195-195, 2561-2801
.env.example (1)
178-179: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/integrations/routeMetadata.ts`:
- Around line 208-221: The hasUsableEnvCredentialValue function correctly
handles both OPENAI_API_KEY and OPENAI_API_KEYS with comma-aware logic, but the
env-only intent guard checks elsewhere in the code only check for OPENAI_API_KEY
and miss OPENAI_API_KEYS, allowing vendor route inference when it should be
prevented. Update all env-only intent guard checks (used in
resolveActiveRouteIdFromEnv and related functions) to check for both
OPENAI_API_KEY and OPENAI_API_KEYS by using the hasUsableEnvCredentialValue
function or applying the same comma-aware usability logic. Additionally, add a
regression test that mirrors the existing MiniMax/OpenAI-key test but uses
OPENAI_API_KEYS to verify that pooled OpenAI credentials prevent vendor route
inference.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 45c9dff0-16e4-4de8-b992-43c7bb2c15ab
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (14)
.env.exampledocs/advanced-setup.mdscripts/system-check.test.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/vendors/openai.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/utils/providerProfile.test.tssrc/utils/providerProfile.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (18)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/integrations/routeMetadata.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/routeMetadata.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.ts
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/routeMetadata.test.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tssrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/openaiShim.test.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
src/integrations/routeMetadata.test.tsscripts/system-check.test.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/integrations/vendors/openai.tsdocs/advanced-setup.mdsrc/integrations/routeMetadata.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
scripts/system-check.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerValidation.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerProfile.tssrc/utils/providerProfile.test.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.ts
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
🔇 Additional comments (16)
.env.example (1)
178-179: LGTM!docs/advanced-setup.md (1)
327-328: LGTM!src/utils/providerProfile.ts (1)
74-74: LGTM!src/utils/providerProfile.test.ts (1)
8-19: LGTM!Also applies to: 139-164
src/services/api/openaiShim.ts (7)
99-108: LGTM!
2174-2197: LGTM!
2798-2876: LGTM!
2886-2888: LGTM!Also applies to: 2913-2981
3093-3106: LGTM!
3190-3195: LGTM!Also applies to: 3232-3232
3317-3338: 403 included with 402/429 as cooldown rather than auth-failure.403 is classified as
'cooldown'alongside 402 and 429, meaning credentials will be temporarily cooled rather than permanently disabled. This is reasonable for providers that return 403 for quota/billing issues, but differs from providers that use 403 for permission errors (which are typically permanent).Current behavior is the safer choice (avoids permanent disable on transient billing issues). Worth noting in docs if providers using 403 for permanent auth failures are encountered.
src/services/api/openaiShim.test.ts (5)
15-15: LGTM!Also applies to: 154-154, 195-195
2561-2589: LGTM!
2621-2687: LGTM!
2689-2759: LGTM!
2761-2801: LGTM!
Reject placeholder values in pooled OpenAI credentials before requests, discovery, diagnostics, and profile generation can use them. Normalize pooled credentials to a single usable key for model discovery, runtime cache partitions, cache probing, and NVIDIA NIM cache lookups. Preserve documented profile precedence by letting live shell credentials override saved pools, carrying OpenCode fallback pools through launch, and redacting individual pool members in profile display. Add regression coverage for pooled credential validation, profile launch/rebuild behavior, discovery/cache callers, diagnostics, provider autodetect, and shim failover semantics.
Import the pooled OpenAI credential validator in provider-recommend and split invalid credentials from unset credentials in user guidance. Add a script-level regression that runs the OpenAI recommendation path with OPENAI_API_KEYS so the ts-nocheck script cannot regress with runtime ReferenceErrors. Scrub pooled OpenAI keys before xAI OAuth profile env construction and loosen the invalid-pool discovery test to assert auth header absence instead of exact header shape.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/commands/provider/provider.tsx (1)
1377-1405:⚠️ Potential issue | 🔴 CriticalAdd tests for OpenAI credential reuse and placeholder validation in wizard.
The wizard step at lines 1377–1405 allows blank submissions to reuse the current session's OpenAI credentials and validates against placeholder values like
SUA_CHAVE. The test suite contains one general wizard test (line 236) that covers TextEntryDialog remounting, but lacks direct coverage for these two OpenAI-specific scenarios:
- Blank submit reusing current pooled/session credentials
- Placeholder rejection (
SUA_CHAVE) viasanitizeOpenAICredentialPoolPer AGENTS.md and CONTRIBUTING.md: "Add or update tests when behavior changes" and "Test the exact provider/model path you changed when possible." Please add focused tests for these flows before merge.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/commands/provider/provider.tsx` around lines 1377 - 1405, Add two focused test cases to cover the OpenAI-specific scenarios in the TextEntryDialog wizard step: first, test that a blank submission when currentOpenAIApiKey exists properly reuses the existing credentials by verifying the apiKey passed to setStep matches the current session's openAIMetadata.apiKey, and second, test that the validate function rejects placeholder values like 'SUA_CHAVE' by confirming that sanitizeOpenAICredentialPool returns false for such inputs and the validation error message is displayed as expected.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/integrations/routeMetadata.test.ts`:
- Around line 124-141: Add a regression test case within the existing test
function that covers a mixed valid and placeholder credentials pool scenario.
After the existing expect statements, add a new test case that calls
getRouteCredentialValue or resolveRouteCredentialValue with OPENAI_API_KEYS set
to a value like 'sk-openai-a,SUA_CHAVE' (combining a valid credential and a
placeholder credential separated by comma) to verify and lock in the current
behavior that any placeholder in a credential pool makes the entire pool
unusable. This ensures the mixed pool scenario is explicitly tested alongside
the existing delimiter-only and placeholder-only pool cases.
In `@src/utils/providerValidation.ts`:
- Around line 302-304: The validation logic in the code block around the
envValue and envValues variables treats each credential source independently,
causing lower-priority placeholders like SUA_CHAVE in OPENAI_API_KEY to
invalidate the validation even when higher-priority sources like OPENAI_API_KEYS
contain valid credentials. Refactor the validation to check credentials in
priority order and only fail if all available credential sources are invalid or
contain placeholder values. Specifically, ensure that when OPENAI_API_KEYS has
valid values, the presence of SUA_CHAVE in OPENAI_API_KEY does not cause
validation failure. Additionally, add a regression test case that verifies the
scenario where OPENAI_API_KEYS is valid and OPENAI_API_KEY contains the
placeholder value SUA_CHAVE passes validation.
---
Outside diff comments:
In `@src/commands/provider/provider.tsx`:
- Around line 1377-1405: Add two focused test cases to cover the OpenAI-specific
scenarios in the TextEntryDialog wizard step: first, test that a blank
submission when currentOpenAIApiKey exists properly reuses the existing
credentials by verifying the apiKey passed to setStep matches the current
session's openAIMetadata.apiKey, and second, test that the validate function
rejects placeholder values like 'SUA_CHAVE' by confirming that
sanitizeOpenAICredentialPool returns false for such inputs and the validation
error message is displayed as expected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b3126fe9-7456-4e5c-af50-2a8bad5ed42c
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationArtifacts.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (64)
.env.exampledocs/advanced-setup.mdscripts/provider-bootstrap.tsscripts/provider-launch.tsscripts/provider-recommend.test.tsscripts/provider-recommend.tsscripts/system-check.test.tsscripts/system-check.tssrc/commands/cache-probe/cache-probe.test.tssrc/commands/cache-probe/cache-probe.tssrc/commands/model/model.test.tsxsrc/commands/model/model.tsxsrc/commands/onboard-github/onboard-github.test.tssrc/commands/onboard-github/onboard-github.tsxsrc/commands/provider/provider.test.tsxsrc/commands/provider/provider.tsxsrc/components/ProviderManager.tsxsrc/integrations/discoveryService.test.tssrc/integrations/discoveryService.tssrc/integrations/gateways/custom.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/hicap.tssrc/integrations/gateways/opencode-go.tssrc/integrations/gateways/opencode.tssrc/integrations/providerUiMetadata.tssrc/integrations/routeMetadata.test.tssrc/integrations/routeMetadata.tssrc/integrations/runtimeMetadata.test.tssrc/integrations/runtimeMetadata.tssrc/integrations/vendors/openai.tssrc/integrations/vendors/venice.tssrc/integrations/vendors/xiaomi-mimo.tssrc/services/api/bootstrap.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/services/api/errors.openaiCompatibility.test.tssrc/services/api/errors.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/services/api/providerConfig.local.test.tssrc/services/api/providerConfig.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/utils/envFile.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/nvidiaNimModels.tssrc/utils/model/openaiModelDiscovery.test.tssrc/utils/model/openaiModelDiscovery.tssrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.test.tssrc/utils/providerAutoDetect.tssrc/utils/providerProfile.test.tssrc/utils/providerProfile.tssrc/utils/providerProfiles.test.tssrc/utils/providerSecrets.test.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tssrc/utils/providerStartupOverrides.tssrc/utils/providerValidation.test.tssrc/utils/providerValidation.tssrc/utils/statusRedaction.test.tssrc/utils/swarm/spawnUtils.test.tssrc/utils/swarm/spawnUtils.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (20)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/swarm/spawnUtils.tssrc/services/api/errors.tssrc/utils/envFile.tssrc/utils/providerAutoDetect.test.tssrc/integrations/runtimeMetadata.tssrc/utils/providerStartupOverrides.tssrc/utils/swarm/spawnUtils.test.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/utils/providerProfiles.test.tssrc/commands/model/model.tsxsrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/utils/model/nvidiaNimModels.tssrc/commands/model/model.test.tsxsrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/components/ProviderManager.tsxsrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/integrations/discoveryService.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/integrations/providerUiMetadata.tssrc/utils/statusRedaction.test.tssrc/commands/provider/provider.tsxsrc/integrations/runtimeMetadata.test.tssrc/commands/onboard-github/onboard-github.tsxsrc/commands/cache-probe/cache-probe.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/commands/cache-probe/cache-probe.tssrc/utils/providerProfile.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
chalkfor terminal color in CLI code
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/services/api/errors.tssrc/services/api/providerConfig.local.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/services/api/providerConfig.tssrc/services/api/bootstrap.tssrc/commands/cache-probe/cache-probe.test.tssrc/services/api/openaiShim.test.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/commands/cache-probe/cache-probe.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/swarm/spawnUtils.tssrc/services/api/errors.tssrc/utils/envFile.tssrc/utils/providerAutoDetect.test.tssrc/utils/providerStartupOverrides.tssrc/utils/swarm/spawnUtils.test.tssrc/services/api/providerConfig.local.test.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tssrc/utils/providerProfiles.test.tssrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.tssrc/utils/model/nvidiaNimModels.tssrc/services/api/providerConfig.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/utils/statusRedaction.test.tssrc/services/api/openaiShim.test.tssrc/utils/providerValidation.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/services/api/errors.tssrc/integrations/runtimeMetadata.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/integrations/routeMetadata.test.tssrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tssrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/integrations/discoveryService.tssrc/integrations/providerUiMetadata.tssrc/integrations/runtimeMetadata.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.ts
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/swarm/spawnUtils.tssrc/services/api/errors.tssrc/utils/envFile.tssrc/utils/providerAutoDetect.test.tssrc/integrations/runtimeMetadata.tssrc/utils/providerStartupOverrides.tssrc/utils/swarm/spawnUtils.test.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tsscripts/provider-bootstrap.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/utils/providerProfiles.test.tssrc/commands/model/model.tsxscripts/system-check.tsscripts/provider-launch.tssrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/utils/model/nvidiaNimModels.tssrc/commands/model/model.test.tsxsrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tsscripts/provider-recommend.test.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/components/ProviderManager.tsxsrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/integrations/discoveryService.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/integrations/providerUiMetadata.tssrc/utils/statusRedaction.test.tsscripts/provider-recommend.tssrc/commands/provider/provider.tsxsrc/integrations/runtimeMetadata.test.tssrc/commands/onboard-github/onboard-github.tsxsrc/commands/cache-probe/cache-probe.test.tsdocs/advanced-setup.mdsrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/commands/cache-probe/cache-probe.tssrc/utils/providerProfile.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/providerAutoDetect.test.tssrc/utils/swarm/spawnUtils.test.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/utils/providerStartupOverrides.test.tssrc/utils/providerProfiles.test.tssrc/utils/opencodeProfile.test.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/commands/model/model.test.tsxscripts/provider-recommend.test.tssrc/utils/envFile.test.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/utils/providerValidation.test.tssrc/utils/statusRedaction.test.tssrc/integrations/runtimeMetadata.test.tssrc/commands/cache-probe/cache-probe.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerProfile.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/providerAutoDetect.test.tssrc/utils/swarm/spawnUtils.test.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/utils/providerStartupOverrides.test.tssrc/utils/providerProfiles.test.tssrc/utils/opencodeProfile.test.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/commands/model/model.test.tsxscripts/provider-recommend.test.tssrc/utils/envFile.test.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/utils/providerValidation.test.tssrc/utils/statusRedaction.test.tssrc/integrations/runtimeMetadata.test.tssrc/commands/cache-probe/cache-probe.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerProfile.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/swarm/spawnUtils.tssrc/services/api/errors.tssrc/utils/envFile.tssrc/utils/providerAutoDetect.test.tssrc/integrations/runtimeMetadata.tssrc/utils/providerStartupOverrides.tssrc/utils/swarm/spawnUtils.test.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tsscripts/provider-bootstrap.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/utils/providerProfiles.test.tssrc/commands/model/model.tsxscripts/system-check.tsscripts/provider-launch.tssrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/utils/model/nvidiaNimModels.tssrc/commands/model/model.test.tsxsrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tsscripts/provider-recommend.test.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/components/ProviderManager.tsxsrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/integrations/discoveryService.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/integrations/providerUiMetadata.tssrc/utils/statusRedaction.test.tsscripts/provider-recommend.tssrc/commands/provider/provider.tsxsrc/integrations/runtimeMetadata.test.tssrc/commands/onboard-github/onboard-github.tsxsrc/commands/cache-probe/cache-probe.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/commands/cache-probe/cache-probe.tssrc/utils/providerProfile.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/swarm/spawnUtils.tssrc/services/api/errors.tssrc/utils/envFile.tssrc/utils/providerAutoDetect.test.tssrc/integrations/runtimeMetadata.tssrc/utils/providerStartupOverrides.tssrc/utils/swarm/spawnUtils.test.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tsscripts/provider-bootstrap.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/utils/providerProfiles.test.tssrc/commands/model/model.tsxscripts/system-check.tsscripts/provider-launch.tssrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/utils/model/nvidiaNimModels.tssrc/commands/model/model.test.tsxsrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tsscripts/provider-recommend.test.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/components/ProviderManager.tsxsrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/integrations/discoveryService.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/integrations/providerUiMetadata.tssrc/utils/statusRedaction.test.tsscripts/provider-recommend.tssrc/commands/provider/provider.tsxsrc/integrations/runtimeMetadata.test.tssrc/commands/onboard-github/onboard-github.tsxsrc/commands/cache-probe/cache-probe.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/commands/cache-probe/cache-probe.tssrc/utils/providerProfile.test.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/swarm/spawnUtils.tssrc/services/api/errors.tssrc/utils/envFile.tssrc/utils/providerAutoDetect.test.tssrc/integrations/runtimeMetadata.tssrc/utils/providerStartupOverrides.tssrc/utils/swarm/spawnUtils.test.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tsscripts/provider-bootstrap.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/utils/providerProfiles.test.tssrc/commands/model/model.tsxscripts/system-check.tsscripts/provider-launch.tssrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/utils/model/nvidiaNimModels.tssrc/commands/model/model.test.tsxsrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tsscripts/provider-recommend.test.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/components/ProviderManager.tsxsrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/integrations/discoveryService.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/integrations/providerUiMetadata.tssrc/utils/statusRedaction.test.tsscripts/provider-recommend.tssrc/commands/provider/provider.tsxsrc/integrations/runtimeMetadata.test.tssrc/commands/onboard-github/onboard-github.tsxsrc/commands/cache-probe/cache-probe.test.tsdocs/advanced-setup.mdsrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/commands/cache-probe/cache-probe.tssrc/utils/providerProfile.test.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/providerSecrets.test.tssrc/services/api/errors.tssrc/utils/providerAutoDetect.test.tssrc/integrations/runtimeMetadata.tssrc/utils/providerStartupOverrides.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/utils/providerProfiles.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/utils/model/nvidiaNimModels.tssrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tssrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/integrations/discoveryService.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/integrations/providerUiMetadata.tssrc/commands/provider/provider.tsxsrc/integrations/runtimeMetadata.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/providerAutoDetect.test.tssrc/utils/swarm/spawnUtils.test.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/utils/providerStartupOverrides.test.tssrc/utils/providerProfiles.test.tssrc/utils/opencodeProfile.test.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/commands/model/model.test.tsxscripts/provider-recommend.test.tssrc/utils/envFile.test.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/utils/providerValidation.test.tssrc/utils/statusRedaction.test.tssrc/integrations/runtimeMetadata.test.tssrc/commands/cache-probe/cache-probe.test.tssrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/services/api/credentialPool.test.tssrc/utils/providerProfile.test.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
src/services/api/errors.openaiCompatibility.test.tssrc/utils/diagnostics/issueReport.test.tssrc/utils/providerSecrets.test.tssrc/utils/swarm/spawnUtils.tssrc/services/api/errors.tssrc/utils/envFile.tssrc/utils/providerAutoDetect.test.tssrc/integrations/runtimeMetadata.tssrc/utils/providerStartupOverrides.tssrc/utils/swarm/spawnUtils.test.tssrc/integrations/vendors/venice.tssrc/services/api/providerConfig.local.test.tsscripts/system-check.test.tssrc/commands/onboard-github/onboard-github.test.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tsscripts/provider-bootstrap.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/utils/providerProfiles.test.tssrc/commands/model/model.tsxscripts/system-check.tsscripts/provider-launch.tssrc/utils/opencodeProfile.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/integrations/routeMetadata.test.tssrc/utils/model/nvidiaNimModels.tssrc/commands/model/model.test.tsxsrc/integrations/gateways/opencode.tssrc/services/api/providerConfig.tssrc/integrations/vendors/openai.tsscripts/provider-recommend.test.tssrc/utils/diagnostics/issueReport.tssrc/utils/envFile.test.tssrc/components/ProviderManager.tsxsrc/integrations/gateways/opencode-go.tssrc/services/api/bootstrap.tssrc/utils/model/nvidiaNimModels.test.tssrc/utils/model/openaiModelDiscovery.test.tssrc/integrations/discoveryService.tssrc/utils/providerValidation.test.tssrc/utils/model/openaiModelDiscovery.tssrc/integrations/providerUiMetadata.tssrc/utils/statusRedaction.test.tsscripts/provider-recommend.tssrc/commands/provider/provider.tsxsrc/integrations/runtimeMetadata.test.tssrc/commands/onboard-github/onboard-github.tsxsrc/commands/cache-probe/cache-probe.test.tsdocs/advanced-setup.mdsrc/services/api/openaiShim.test.tssrc/integrations/discoveryService.test.tssrc/utils/providerValidation.tssrc/integrations/routeMetadata.tssrc/services/api/openaiShim.tssrc/services/api/credentialPool.test.tssrc/services/api/credentialPool.tssrc/utils/providerProfile.tssrc/commands/cache-probe/cache-probe.tssrc/utils/providerProfile.test.ts
src/**/*provider*.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Provider implementations must follow documented patterns in docs/integrations/
Files:
src/utils/providerSecrets.test.tssrc/utils/providerAutoDetect.test.tssrc/utils/providerStartupOverrides.tssrc/services/api/providerConfig.local.test.tssrc/utils/providerSecrets.tssrc/utils/providerStartupOverrides.test.tssrc/utils/providerProfiles.test.tssrc/utils/providerAutoDetect.tssrc/commands/provider/provider.test.tsxsrc/services/api/providerConfig.tssrc/utils/providerValidation.test.tssrc/integrations/providerUiMetadata.tssrc/commands/provider/provider.tsxsrc/utils/providerValidation.tssrc/utils/providerProfile.tssrc/utils/providerProfile.test.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/runtimeMetadata.tssrc/integrations/vendors/venice.tssrc/integrations/vendors/xiaomi-mimo.tssrc/integrations/gateways/hicap.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/integrations/gateways/custom.tssrc/integrations/routeMetadata.test.tssrc/integrations/gateways/opencode.tssrc/integrations/vendors/openai.tssrc/integrations/gateways/opencode-go.tssrc/integrations/discoveryService.tssrc/integrations/providerUiMetadata.tssrc/integrations/runtimeMetadata.test.tssrc/integrations/discoveryService.test.tssrc/integrations/routeMetadata.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
scripts/system-check.test.tsscripts/provider-bootstrap.tsscripts/system-check.tsscripts/provider-launch.tsscripts/provider-recommend.test.tsscripts/provider-recommend.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
commanderfor CLI argument parsing
Files:
src/commands/onboard-github/onboard-github.test.tssrc/commands/cache-probe/cache-probe.test.tssrc/commands/cache-probe/cache-probe.ts
src/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use React + Ink for terminal UI implementations
Files:
src/components/ProviderManager.tsx
docs/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update docs when setup, commands, or user-facing behavior changes
Files:
docs/advanced-setup.md
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}
⚙️ CodeRabbit configuration file
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.
Files:
docs/advanced-setup.md
🪛 React Doctor (0.5.6)
src/components/ProviderManager.tsx
[warning] 1348-1348: This component misses React Compiler's automatic memoization & re-renders more than it should: This value cannot be modified. Rewrite the flagged code so the compiler can optimize it.
Modifying a variable defined outside a component or hook is not allowed. Consider using an effect.
(immutability)
[warning] 1399-1399: This component misses React Compiler's automatic memoization & re-renders more than it should: This value cannot be modified. Rewrite the flagged code so the compiler can optimize it.
Modifying a variable defined outside a component or hook is not allowed. Consider using an effect.
(immutability)
🔇 Additional comments (61)
.env.example (1)
178-179: LGTM!docs/advanced-setup.md (1)
327-328: LGTM!Also applies to: 436-436
src/services/api/credentialPool.ts (1)
1-124: LGTM!src/services/api/credentialPool.test.ts (1)
1-61: LGTM!src/services/api/openaiShim.ts (1)
14-14: LGTM!Also applies to: 99-109, 2199-2223, 2853-2853, 2871-2931, 2951-2967, 2992-3059, 3172-3172, 3182-3185, 3269-3288, 3325-3325, 3447-3467
src/services/api/errors.ts (1)
115-115: LGTM!src/services/api/errors.openaiCompatibility.test.ts (1)
101-116: LGTM!src/services/api/openaiShim.test.ts (1)
15-15: LGTM!Also applies to: 155-155, 197-197, 2536-2596, 2706-2735, 2766-3044
src/integrations/routeMetadata.ts (1)
15-15: LGTM!Also applies to: 200-229, 498-498, 509-509, 522-522, 607-607, 620-627
src/integrations/providerUiMetadata.ts (1)
1-1: LGTM!Also applies to: 31-49
src/utils/diagnostics/issueReport.ts (1)
15-15: LGTM!Also applies to: 276-288
src/utils/diagnostics/issueReport.test.ts (1)
72-96: LGTM!src/utils/providerStartupOverrides.test.ts (1)
16-17: LGTM!Also applies to: 38-39
src/utils/providerStartupOverrides.ts (1)
15-15: LGTM!src/utils/providerAutoDetect.ts (1)
37-37: LGTM!Also applies to: 73-93, 164-167
src/utils/providerAutoDetect.test.ts (1)
79-95: LGTM!src/utils/providerProfiles.test.ts (1)
35-35: LGTM!Also applies to: 1560-1587
src/utils/statusRedaction.test.ts (1)
99-100: LGTM!Also applies to: 115-122
src/utils/swarm/spawnUtils.test.ts (1)
35-44: LGTM!src/utils/swarm/spawnUtils.ts (1)
110-110: LGTM!scripts/system-check.ts (1)
334-336: LGTM!Also applies to: 502-509
scripts/system-check.test.ts (1)
26-26: LGTM!Also applies to: 187-198, 200-219, 221-238
src/utils/envFile.ts (1)
94-94: LGTM!src/utils/envFile.test.ts (1)
20-20: LGTM!Also applies to: 226-248
src/utils/providerSecrets.ts (1)
13-13: LGTM!Also applies to: 192-195
src/utils/providerSecrets.test.ts (1)
221-233: LGTM!src/utils/providerProfile.ts (1)
13-13: LGTM!Also applies to: 75-75, 154-154, 662-745, 759-788, 798-798, 836-836, 1581-1586, 1600-1619, 1629-1652, 1788-1793
src/utils/providerProfile.test.ts (1)
8-19: LGTM!Also applies to: 37-37, 140-166, 748-760, 1334-1418, 1847-1910, 1927-1962
src/utils/opencodeProfile.test.ts (1)
136-177: LGTM!src/commands/provider/provider.tsx (1)
53-53: LGTM!Also applies to: 481-484
src/commands/provider/provider.test.tsx (1)
333-378: LGTM!src/components/ProviderManager.tsx (1)
1323-1331: LGTM!Also applies to: 1346-1348, 1396-1400
src/commands/onboard-github/onboard-github.tsx (1)
47-47: LGTM!Also applies to: 107-107, 135-135
src/commands/onboard-github/onboard-github.test.ts (1)
89-89: LGTM!Also applies to: 107-107, 124-124
scripts/provider-bootstrap.ts (1)
170-177: LGTM!scripts/provider-launch.ts (1)
12-14: LGTM!Also applies to: 232-243
scripts/provider-recommend.ts (1)
17-19: LGTM!Also applies to: 39-54, 164-164, 205-206, 272-285
scripts/provider-recommend.test.ts (1)
1-85: LGTM!src/integrations/gateways/custom.ts (1)
47-47: LGTM!src/integrations/gateways/gitlawb-opengateway.ts (1)
14-24: LGTM!src/integrations/vendors/openai.ts (1)
9-13: LGTM!Also applies to: 25-43
src/integrations/vendors/venice.ts (1)
34-36: LGTM!src/integrations/vendors/xiaomi-mimo.ts (1)
69-71: LGTM!src/integrations/gateways/hicap.ts (1)
48-50: LGTM!src/integrations/gateways/opencode-go.ts (1)
3-50: LGTM!Also applies to: 68-70, 81-87
src/integrations/gateways/opencode.ts (1)
3-70: LGTM!Also applies to: 92-92, 101-107
src/integrations/runtimeMetadata.ts (1)
28-28: LGTM!Also applies to: 281-365, 399-405
src/integrations/runtimeMetadata.test.ts (1)
84-163: LGTM!Also applies to: 283-305
src/commands/cache-probe/cache-probe.ts (1)
2-2: LGTM!Also applies to: 43-83, 231-243
src/commands/model/model.tsx (1)
36-36: LGTM!Also applies to: 331-337
src/commands/model/model.test.tsx (1)
32-32: LGTM!Also applies to: 213-213, 2198-2261
src/services/api/bootstrap.ts (1)
9-9: LGTM!Also applies to: 163-170
src/services/api/providerConfig.ts (1)
932-932: LGTM!src/services/api/providerConfig.local.test.ts (1)
15-15: LGTM!Also applies to: 41-41, 141-153
src/commands/cache-probe/cache-probe.test.ts (1)
1-74: LGTM!src/integrations/discoveryService.ts (1)
32-32: LGTM!Also applies to: 159-173, 456-466
src/integrations/discoveryService.test.ts (1)
18-18: LGTM!Also applies to: 59-59, 92-92, 448-489, 491-519
src/utils/model/nvidiaNimModels.test.ts (1)
5-50: LGTM!Also applies to: 81-98, 145-166
src/utils/model/nvidiaNimModels.ts (1)
12-12: LGTM!Also applies to: 192-226
src/utils/model/openaiModelDiscovery.ts (1)
2-2: LGTM!Also applies to: 53-57
src/utils/model/openaiModelDiscovery.test.ts (1)
14-15: LGTM!Also applies to: 27-64, 77-78, 104-197
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/utils/model/openaiModelDiscovery.ts`:
- Around line 53-60: The apiKey assignment in the credential resolution logic
incorrectly prioritizes the presence of OPENAI_API_KEYS entries over their
usability. The hasPooledCredentialSource check forces apiKey to undefined when
OPENAI_API_KEYS exists but contains only unusable credentials (like
placeholders), blocking fallback to OPENAI_API_KEY. Instead, simplify the logic
to remove the hasPooledCredentialSource conditional entirely and just use
pooledCredential ?? firstUsableCredential(process.env.OPENAI_API_KEY), which
will naturally fall back to the singular key when no usable pooled credential is
found. Additionally, add a regression test in openaiModelDiscovery.test.ts
covering the scenario where OPENAI_API_KEYS contains mixed valid and placeholder
values (e.g., 'sk-openai-a,SUA_CHAVE') alongside a valid OPENAI_API_KEY to
ensure the fallback behavior works correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: c822cc6f-c3dd-486a-8145-b7ef5400f2a0
📒 Files selected for processing (2)
src/integrations/routeMetadata.test.tssrc/utils/model/openaiModelDiscovery.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (13)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports
Files:
src/utils/model/openaiModelDiscovery.tssrc/integrations/routeMetadata.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Use
execafor child processes
Files:
src/utils/model/openaiModelDiscovery.ts
**/*.{ts,tsx,js,jsx,py,json,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow the existing code style in the touched files
Files:
src/utils/model/openaiModelDiscovery.tssrc/integrations/routeMetadata.test.ts
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep comments useful and concise
Files:
src/utils/model/openaiModelDiscovery.tssrc/integrations/routeMetadata.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Follow TypeScript strict mode and type safety practices by running typecheck before submitting
Files:
src/utils/model/openaiModelDiscovery.tssrc/integrations/routeMetadata.test.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/utils/model/openaiModelDiscovery.tssrc/integrations/routeMetadata.test.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/utils/model/openaiModelDiscovery.tssrc/integrations/routeMetadata.test.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
- Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.- `src/integration...
Files:
src/utils/model/openaiModelDiscovery.tssrc/integrations/routeMetadata.test.ts
{src/integrations/**/*.ts,src/services/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Test the exact provider/model path you changed when possible for provider modifications
Files:
src/integrations/routeMetadata.test.ts
src/integrations/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Check existing provider implementations before adding a new pattern
Files:
src/integrations/routeMetadata.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add or update tests when the change affects behavior
Files:
src/integrations/routeMetadata.test.ts
**/*.test.{ts,tsx,js}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Test the exact provider/model path you changed when possible
Files:
src/integrations/routeMetadata.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/integrations/routeMetadata.test.ts
🔇 Additional comments (1)
src/integrations/routeMetadata.test.ts (1)
10-10: LGTM!Also applies to: 36-62, 97-151, 200-200, 297-305
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
…ites The cross-profile tests mock.module'd ../providerProfiles, ./providers, ../auth and ../../services/api/providerConfig per test. bun's mock.module is process-wide and mock.restore() does not undo it, so these persisted into later files — most damagingly the providerConfig mock, which replaced the module with a single-function stub and stripped resolveProviderRequest / getAdditionalModelOptionsCacheScope from providerConfig.local's suite (now adjacent after the rebase onto Twigpine#1706). Install each mock once at module load, keep the full export surface, and gate the overrides on module-level flags cleared in beforeEach/afterEach so the persisted mocks are transparent passthroughs for every other suite. Same pattern as the cross-spawn / install-surfaces leak fixes.
…ites The cross-profile tests mock.module'd ../providerProfiles, ./providers, ../auth and ../../services/api/providerConfig per test. bun's mock.module is process-wide and mock.restore() does not undo it, so these persisted into later files — most damagingly the providerConfig mock, which replaced the module with a single-function stub and stripped resolveProviderRequest / getAdditionalModelOptionsCacheScope from providerConfig.local's suite (now adjacent after the rebase onto Twigpine#1706). Install each mock once at module load, keep the full export surface, and gate the overrides on module-level flags cleared in beforeEach/afterEach so the persisted mocks are transparent passthroughs for every other suite. Same pattern as the cross-spawn / install-surfaces leak fixes.
…ites The cross-profile tests mock.module'd ../providerProfiles, ./providers, ../auth and ../../services/api/providerConfig per test. bun's mock.module is process-wide and mock.restore() does not undo it, so these persisted into later files — most damagingly the providerConfig mock, which replaced the module with a single-function stub and stripped resolveProviderRequest / getAdditionalModelOptionsCacheScope from providerConfig.local's suite (now adjacent after the rebase onto Twigpine#1706). Install each mock once at module load, keep the full export surface, and gate the overrides on module-level flags cleared in beforeEach/afterEach so the persisted mocks are transparent passthroughs for every other suite. Same pattern as the cross-spawn / install-surfaces leak fixes.
…ites The cross-profile tests mock.module'd ../providerProfiles, ./providers, ../auth and ../../services/api/providerConfig per test. bun's mock.module is process-wide and mock.restore() does not undo it, so these persisted into later files — most damagingly the providerConfig mock, which replaced the module with a single-function stub and stripped resolveProviderRequest / getAdditionalModelOptionsCacheScope from providerConfig.local's suite (now adjacent after the rebase onto Twigpine#1706). Install each mock once at module load, keep the full export surface, and gate the overrides on module-level flags cleared in beforeEach/afterEach so the persisted mocks are transparent passthroughs for every other suite. Same pattern as the cross-spawn / install-surfaces leak fixes.
… piece 2) (#1164) * feat(model-picker): surface inactive provider profiles in /model When a user configures multiple providerProfiles (Kimi + Z.AI + OpenRouter + SambaNova in the #1119 repro, but the pattern fits any multi-provider setup), switching the main session between them currently requires round-tripping through /provider — /model only shows the active profile's models. Make /model the single switcher: - ModelOption gains an optional `switchToProfileId`. Existing options leave it unset and behave exactly as today. - `getInactiveProviderProfileOptions` enumerates every configured profile that isn't the active one and emits a picker entry per model, labelled `<model> · <profile.name>` so the user can see the choice changes providers, not just models. - Each option's `value` is encoded with `__switch_profile__:<id>:<model>` so the picker's plain-string `value` channel stays the source of truth and same-named models under different base URLs (`gpt-4o` on multiple OpenAI-compatible endpoints) stay disambiguated. - /model's handleSelect detects the prefix, calls `setActiveProviderProfile` (same path /provider uses — applies env, persists active profile, refreshes startup file), then sets `mainLoopModel` to the bare model string. Only surfaces inactive options when `CLAUDE_CODE_PROVIDER_PROFILE_ENV_APPLIED` is set, so users who haven't opted into the multi-profile workflow at all don't see the affordance. Tests cover round-trip encoding (including OpenRouter-style colon-bearing model strings), the active-filter, the multi-model explosion, and that `getModelOptions()` 3P path includes the inactive options only when the profile env is applied. Combined invocation with the rest of `src/utils/model/` + `src/commands/model/` + `src/utils/providerProfiles.test.ts` runs clean to guard against mock-leak (per the 2026-04-30 lesson — spreads `import * as actual` for every `mock.module` factory). Refs #1119 * fix(model-picker): run fast-mode cleanup on cross-profile switch The new switch-profile branch returned before reaching the fast-mode reconciliation, so a user with fastMode latched on Anthropic Opus could switch to an OpenAI profile and silently keep fastMode on even though the new model can't support it. Extract the cleanup into a pure helper `reconcileFastModeForSwitch` and call it from both branches. Refs #1119. * fix(model-picker): decode cross-profile values before effort/display lookup Inactive-profile entries encode the picker value as `__switch_profile__:<profileId>:<model>`, but `resolveOptionModel` forwarded the raw string straight to `parseUserSpecifiedModel`. For a reasoning-capable cross-profile entry such as `gpt-5.4`, `modelSupportsEffort()` then saw the prefixed string and reported "Effort not supported", and `handleSelect` dropped the toggled effort even when the underlying model accepts it. Run `parseSwitchProfileValue` first; when it matches, hand the bare target model to `parseUserSpecifiedModel` so effort capability, default-effort lookup, and display-name resolution all key off the real model id. * fix(model-picker): include inactive profiles on local OpenAI-compatible scope The inactive-profile compute lived after the `getAdditionalModelOptionsCacheScope()?.startsWith('openai:')` early return, so users with a local OpenAI-compatible profile active (Ollama, lm-studio, any localhost endpoint) never saw the cross-profile switcher in `/model`. They still had to round-trip through `/provider` to change profile. Hoist `profileEnvApplied`, the active-profile lookup, and `getInactiveProviderProfileOptions(activeProfileId)` above the early return, and append `inactiveProfileOptions` to the local-OpenAI branch return value. Other branches (Claude.AI, MiMo, MiniMax, ant) were already either irrelevant or have their own gating. Test: new regression in modelOptions.crossProfile.test.ts pins `getAdditionalModelOptionsCacheScope` to an `openai:` value and confirms the inactive profile still surfaces with a parseable `__switch_profile__` value. * fix(model-picker): apply the allowlist to the decoded cross-profile model filterModelOptionsByAllowlist evaluated cross-profile options by their encoded __switch_profile__:<id>:<model> value, so an availableModels allowlist that permits the bare target (e.g. glm-5.1) dropped every inactive-profile entry. Check the allowlist against parseSwitchProfileValue(value)?.model ?? value, and cover both the allowed and denied cases. * fix(model-picker): only surface cross-profile switch options on the /model path The inactive-profile entries come from the shared getModelOptions() list, but only the /model command's onSelect decodes __switch_profile__ values and activates the target profile. The prompt hotkey and Settings pickers wrote the encoded value straight to mainLoopModel, sending an invalid model string. Gate these options behind a new allowProfileSwitch prop that only the /model command sets; inline pickers no longer surface an option they cannot honor. Also apply the org allowlist to the decoded target model in the /model select handler. * test(model-picker): drop flaky cross-profile allowlist case The decoded-allowlist assertion drove the org allowlist through the shared session settings cache, which is racy across bun's single-process run and could leak availableModels into sibling suites (the providerConfig cache-scope tests went red in CI). The decode itself is a one-line guard already exercised by the parseSwitchProfileValue round-trip coverage, so remove the unreliable case rather than ship CI flake. Also snapshot the real provider/auth modules before mocking so each harness call rebuilds its mock from a clean base instead of a previous test's overrides (bun live-repoints the imported namespace to the active mock). * test(model-picker): stop cross-profile mocks leaking into provider suites The cross-profile tests mock.module'd ../providerProfiles, ./providers, ../auth and ../../services/api/providerConfig per test. bun's mock.module is process-wide and mock.restore() does not undo it, so these persisted into later files — most damagingly the providerConfig mock, which replaced the module with a single-function stub and stripped resolveProviderRequest / getAdditionalModelOptionsCacheScope from providerConfig.local's suite (now adjacent after the rebase onto #1706). Install each mock once at module load, keep the full export surface, and gate the overrides on module-level flags cleared in beforeEach/afterEach so the persisted mocks are transparent passthroughs for every other suite. Same pattern as the cross-spawn / install-surfaces leak fixes. * fix(model): reconcile fast mode before activating the switched profile In the cross-profile /model switch path, reconcileFastModeForSwitch ran after setActiveProviderProfile. The reconciler gates on isFastModeEnabled(), which reads the *active* provider — so once the target profile is activated it reflects the new (fast-mode-less) provider and short-circuits to 'unchanged', leaving fastMode latched on for a model that can't use it. Compute the reconciliation before activating the profile, so it evaluates against the source provider and correctly returns 'off' for an unsupported target. Add a command-level regression test that drives handleSelect with a __switch_profile__ value while setActiveProviderProfile flips the fast-mode state, and asserts fastMode is set to false (it fails if the call order regresses). * fix(model): re-check fast mode after activating a switched profile The pre-activation reconcile gates on the source provider, so its 'on' result is stale when the target provider cannot run fast mode even though the target model name passes the source-side support check (e.g. a third-party shim exposing a claude-opus-* model). Re-evaluate isFastModeEnabled / supported / available after setActiveProviderProfile and force fastMode off when it is no longer genuinely supported. Add a command-level regression test for that path and wrap the cross-profile test cleanup in try/finally so a failing assertion still unmounts the Ink instance (jatmn review, #1119). * test(model-picker): cover cross-profile allowlist with isolated settings Re-add the regression dropped in 06a0c80: filterModelOptionsByAllowlist must evaluate the allowlist against the decoded target model, not the encoded __switch_profile__ wrapper. Uses this suite's per-test settings cache (reset in afterEach) instead of the shared cache that made the earlier version flaky (jatmn review, #1119). * test(model-picker): make the cross-profile allowlist test leak-proof The new allowlist test drove availableModels through setSessionSettingsCache, but sibling suites (ModelPicker, ProviderManager, ...) mock.module both settings.js (getSettings_DEPRECATED) and modelAllowlist.js (isModelAllowed) process-wide, so in the full sequential run the leaked stubs defeated the cache and the denied option was not filtered (smoke-and-tests red on the full suite, green in isolation). Drive the allowlist deterministically from this suite instead: install-once, gated, passthrough mocks of getSettings_DEPRECATED (the filter gate) and isModelAllowed (the per-option check), both keyed off a single activeSettingsOverride and cleared in afterEach. Same gated-passthrough pattern as the suite's existing providerConfig/providers/auth/profiles mocks and the agent.test.ts allowlist approach. * fix(model): keep cross-profile switch options out of the SDK models list getModelOptions() now returns inactive-profile entries encoded as __switch_profile__:<id>:<model>. print.ts mapped those straight into the ModelInfo list returned to SDK/web callers, exposing UI-only values that are not selectable model ids. Filter them with parseSwitchProfileValue before building modelInfos. Add ModelPicker coverage for the allowProfileSwitch filter (hidden inline, shown when allowed) and document cross-profile /model switching in the provider-profile docs. * test(model-picker): prove cross-profile switch options never reach SDK models Extract selectSdkModelOptions as the single gate the SDK modelInfos builder runs every getModelOptions() entry through, and cover it directly: an encoded __switch_profile__:<id>:<model> option is dropped while real model ids pass through. Fails if an inactive-profile affordance ever leaks into the initialize.models response again (#1119). * docs(model-picker): clarify the env gate for inactive-profile entries The inactive-profile models only appear when the provider-profile env workflow is active (CLAUDE_CODE_PROVIDER_PROFILE_ENV_APPLIED=1), not for every multi-profile setup. Spell that out and restore the local-only `--provider ollama` guidance that was folded into the paragraph. * fix(model-picker): gate SDK option filter on switchToProfileId marker selectSdkModelOptions filtered on the encoded __switch_profile__ value prefix, which also reserved that prefix for every custom model id. A real configured model whose id starts with __switch_profile__: would vanish from the SDK models response and non-switching pickers. Key the gate on the explicit switchToProfileId marker, which only synthesized switch options carry, and add the collision regression. Refs #1119 * fix(model-picker): reuse switch confirmation for cross-profile selections The cross-profile branch built its own "Switched to" message and returned before the regular path appended the selected effort and the "Billed as extra usage" notice, hiding cost-impacting feedback when a reasoning/extra-usage target was chosen through an inactive profile. Append effort and the extra-usage check to the switch confirmation. Refs #1119 * fix(model-picker): surface inactive profiles on the active Ollama path The isOllamaProvider() early return ran before the inactive-profile options were computed, so an active local Ollama profile saw only its own models and lost the cross-profile switcher, forcing the /provider round-trip this feature removes. Hoist the inactive-profile compute above the Ollama branch and append it to the Ollama returns. Refs #1119 * fix(model): surface inactive profiles on all provider branches; decode only real switch options Two follow-ups to the #1119 unified /model switcher: - inactiveProfileOptions was computed before the early-return branches but only appended on Ollama / local-scope / PAYG paths. The GitHub Copilot, NVIDIA NIM, MiniMax, Xiaomi MiMo, ant, and Claude-subscriber branches returned first, so a user with a saved profile active on any of those routes lost the cross-profile entries and had to round-trip through /provider. Append the (env-gated, so empty unless a profile is applied) inactive options on those branches too. - filterModelOptionsByAllowlist decoded any value starting with `__switch_profile__:` via parseSwitchProfileValue, even a normal custom model id that merely shares that prefix, evaluating the allowlist against the wrong inner model. Gate the decode on the `switchToProfileId` marker (the type's documented contract) so non-switch ids are checked verbatim. Extends the cross-profile harness with gated getAPIProvider / NVIDIA / subscriber overrides and adds branch-append + verbatim-allowlist regressions (red-green). * fix(model): key profile-switch handling on the marker across picker and command The allowlist/SDK paths already used the switchToProfileId marker, but two surfaces still keyed on the raw `__switch_profile__:` value prefix: - ModelPicker's inline-picker filter hid any option whose value started with the prefix, so a real custom model id like `__switch_profile__:vendor:gpt-5.4` disappeared from prompt/settings pickers. It now filters on `switchToProfileId === undefined`. - the /model command decoded parseSwitchProfileValue(model) for any prefixed string and tried to activate the encoded profile id, so selecting such a custom model activated a nonexistent profile instead of setting the literal model. It now only treats the value as a switch when the decoded profile id maps to a real configured provider profile — which every synthesized switch option does, and a prefix-colliding custom id does not. Drops the now-unused SWITCH_PROFILE_VALUE_PREFIX import from ModelPicker. Adds a picker regression (marked switch hidden, prefixed custom model stays visible) and completes the cross-profile branch coverage (MiniMax, Xiaomi MiMo, ant) so every branch that appends inactive-profile options is locked. * test(model): register target profiles in cross-profile switch tests The /model command now only treats a `__switch_profile__:` value as a switch when its decoded profile id maps to a real configured provider profile. The cross-profile switch tests set up setActiveProviderProfile but left the shared getProviderProfiles mock empty, so the new guard classified their switch values as literal models and the fast-mode / effort / extra-usage assertions no longer ran. Register each test's target profile via getProviderProfiles so the switch path executes as intended. * fix(model): gate cross-profile switches on the selected option marker Selecting a value that merely parses as `__switch_profile__:<profileId>:<model>` activated the provider whenever <profileId> existed, so a literal custom model id such as `__switch_profile__:profile_openai:gpt-5-mini` wrongly switched the active provider instead of being applied verbatim. Thread the picked option's `switchToProfileId` marker from ModelPicker.onSelect (selectOptions already carries it) and only activate a profile when the marker matches the decoded id. The effort/display resolver had the same gap — it decoded every prefixed value; gate it on a genuine marker-backed switch option too. Add a regression asserting a marker-less prefixed id is applied literally. * test(model): cover Max/Team Premium and empty-catalog switch-append paths The cross-profile branch-coverage suite exercised the populated-catalog returns but not the Max/Team Premium subscriber early return nor the empty-catalog fallbacks (NVIDIA/MiniMax/Xiaomi), which are the same paths that previously dropped the inactive-profile switch options. Lock them so every changed return that appends `...inactiveProfileOptions` is covered. * fix(model): keep inactive-profile switch options in /model discovery overrides The interactive /model command passes an optionsOverride into ModelPicker for descriptor-backed and legacy OpenAI-compatible discovery contexts, built from mergeActiveProfileModelOptions which only merges the ACTIVE profile's route models. Because the picker renders optionsOverride ?? getModelOptions(), the inactive-profile switch entries getModelOptions() appends never reached those paths, so the unified switcher vanished for provider-profile routes (OpenRouter/Kimi/MiniMax, refreshed local profiles). Re-append the same inactive-profile switch options (allowlist-filtered on the decoded target) to any override list before handing it to the picker. * fix(model): base the switch marker on the presented option, treat ties as ambiguous The picker derived switchToProfileId with selectOptions.find(value===...), and the effort/display resolver decoded when any getModelOptions() entry with the same value carried the marker. If a literal custom model id collided with an encoded switch value, the literal could borrow a different same-value option's marker and wrongly activate a provider. Add resolveSelectedSwitchProfileId, which keys on the actual presented option and treats duplicate-value matches as ambiguous (no switch), and route both the onSelect marker and the decode decision through it.
Summary
Closes #901.
Adds OpenAI-compatible credential pool failover for users with multiple API keys/accounts:
OPENAI_API_KEYS=key-a,key-band comma-separatedOPENAI_API_KEYapi-key, descriptor auth headers, custom auth headers, Bankr, GitHub, Gemini fallback)OPENAI_API_KEYSUser impact
Users can configure multiple OpenAI-compatible/custom-provider credentials and OpenClaude will fail over automatically instead of requiring manual key switching. Direct multi-Codex-OAuth/auth.json account pooling is not part of this PR; this implements the OpenAI-compatible/custom API-key failover path for #901.
Risk surface
This changes auth and outbound retry behavior for OpenAI-compatible routes. The sensitive areas are credential precedence, per-attempt header construction, retry classification after 401/402/403/429 responses, and provider-specific fallback keys. The implementation keeps provider-specific credentials ahead of generic OpenAI pools, preserves custom auth headers, treats configured
OPENAI_API_KEYS/OPENAI_API_KEYas explicit credentials ahead of xAI OAuth fallback, disables keys only in memory for the client lifetime, and adds focused regression coverage for startup validation, route discovery, Opengateway precedence, Azureapi-key, pluralOPENAI_API_KEYS, and comma-separated singularOPENAI_API_KEY.Provider paths tested
OPENAI_API_KEYSOPENAI_API_KEYrotation withOPENAI_API_KEYSunsetOPENAI_API_KEYSOPENAI_API_KEYSOPENAI_API_KEYfallback withOPENAI_API_KEYSprecedenceapi-keyauth rotationOPENAI_API_KEYSbun run test:providerValidation
bun test src/integrations/routeMetadata.test.ts src/utils/providerValidation.test.ts src/services/api/credentialPool.test.ts src/services/api/openaiShim.test.ts(209 pass)bun test scripts/system-check.test.ts src/integrations/routeMetadata.test.ts src/utils/providerValidation.test.ts(96 pass)bun run test:provider(848 pass)bun run integrations:checkbun run smokebun run typecheckbun run typecheck:type-testsbun run security:pr-scan -- --base upstream/mainbun run doctor:runtimebun run check(build/smoke/deadcode passed;test:fullfails on three pre-existing Windows path tests)bun run checkfailures reproduce on cleanupstream/maininwork/openclaude-baseline:redactPathForStatus > shortens POSIX home directory paths to ~redactPathForStatus > handles the home directory exactlyhookSourceDescriptionDisplayString > uses the canonical OpenClaude plugin path for plugin hooksPlugin hooks (~/.openclaude/plugins/*/hooks/hooks.json)Plugin hooks (~\.openclaude\plugins\*\hooks\hooks.json)Screenshots
N/A - no UI, terminal presentation, or VS Code extension changes.
Summary by CodeRabbit
New Features
OPENAI_API_KEYS(comma-separated) with automatic failover, cooldown/retry behavior, and consistent selection across requests, discovery, and cache probing.Bug Fixes
OPENAI_API_KEYSandOPENAI_API_KEY, including correct handling of delimiter-only and placeholder entries.Documentation
.env.exampleand advanced setup docs to document pooling precedence/behavior.Tests