Skip to content

feat(api): add OpenAI-compatible credential pool failover - #1706

Merged
kevincodex1 merged 14 commits into
Twigpine:mainfrom
jatmn:issue-901
Jun 23, 2026
Merged

kevincodex1 merged 14 commits into
Twigpine:mainfrom
jatmn:issue-901

Conversation

@jatmn

@jatmn jatmn commented Jun 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Closes #901.

Adds OpenAI-compatible credential pool failover for users with multiple API keys/accounts:

  • support OPENAI_API_KEYS=key-a,key-b and comma-separated OPENAI_API_KEY
  • rotate credentials on auth/quota/rate-limit failures
  • persist pool state on the shim client so cooldowns/evictions survive across requests
  • preserve provider-specific credentials and auth header behavior (Azure api-key, descriptor auth headers, custom auth headers, Bankr, GitHub, Gemini fallback)
  • make startup validation/model credential discovery recognize OPENAI_API_KEYS

User 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_KEY as 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, Azure api-key, plural OPENAI_API_KEYS, and comma-separated singular OPENAI_API_KEY.

Provider paths tested

  • OpenAI-compatible Bearer auth via OPENAI_API_KEYS
  • Comma-separated OPENAI_API_KEY rotation with OPENAI_API_KEYS unset
  • Startup/provider validation with only OPENAI_API_KEYS
  • Route credential/model-discovery lookup for OPENAI_API_KEYS
  • Generic OPENAI_API_KEY fallback with OPENAI_API_KEYS precedence
  • Gitlawb Opengateway provider-specific credential precedence over generic pools
  • Azure-style api-key auth rotation
  • Exhausted auth-disabled key pools are not reused across client requests
  • Placeholder validation for OPENAI_API_KEYS
  • Existing provider shim suite via bun run test:provider

Validation

  • 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:check
  • bun run smoke
  • bun run typecheck
  • bun run typecheck:type-tests
  • bun run security:pr-scan -- --base upstream/main
  • bun run doctor:runtime
  • bun run check (build/smoke/deadcode passed; test:full fails on three pre-existing Windows path tests)
    • The same bun run check failures reproduce on clean upstream/main in work/openclaude-baseline:
      • redactPathForStatus > shortens POSIX home directory paths to ~
      • redactPathForStatus > handles the home directory exactly
      • hookSourceDescriptionDisplayString > uses the canonical OpenClaude plugin path for plugin hooks
    • Focused rerun shows the hook failure is the canonical path separator expectation:
      • expected Plugin hooks (~/.openclaude/plugins/*/hooks/hooks.json)
      • received Plugin hooks (~\.openclaude\plugins\*\hooks\hooks.json)

Screenshots

N/A - no UI, terminal presentation, or VS Code extension changes.

Summary by CodeRabbit

  • New Features

    • Added support for rotating multiple OpenAI-compatible API keys via OPENAI_API_KEYS (comma-separated) with automatic failover, cooldown/retry behavior, and consistent selection across requests, discovery, and cache probing.
  • Bug Fixes

    • Improved precedence and fallback between OPENAI_API_KEYS and OPENAI_API_KEY, including correct handling of delimiter-only and placeholder entries.
    • Updated guidance and credential validation/remediation messaging to reference both variables.
  • Documentation

    • Updated .env.example and advanced setup docs to document pooling precedence/behavior.
  • Tests

    • Added/expanded automated coverage for pooling, rotation, validation edge cases, and environment hygiene.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 81726511-b738-44f0-acab-ac08a46f9cdb

📥 Commits

Reviewing files that changed from the base of the PR and between c349902 and ecdf885.

📒 Files selected for processing (2)
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/utils/model/openaiModelDiscovery.ts
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (11)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/utils/model/openaiModelDiscovery.ts
  • src/utils/model/openaiModelDiscovery.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/model/openaiModelDiscovery.ts
  • src/utils/model/openaiModelDiscovery.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/model/openaiModelDiscovery.ts
  • src/utils/model/openaiModelDiscovery.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/utils/model/openaiModelDiscovery.ts
  • src/utils/model/openaiModelDiscovery.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.ts
  • src/utils/model/openaiModelDiscovery.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.ts
  • src/utils/model/openaiModelDiscovery.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.ts
  • src/utils/model/openaiModelDiscovery.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • src/utils/model/openaiModelDiscovery.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • src/utils/model/openaiModelDiscovery.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • src/utils/model/openaiModelDiscovery.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/model/openaiModelDiscovery.test.ts
🔇 Additional comments (2)
src/utils/model/openaiModelDiscovery.ts (1)

2-2: LGTM!

Also applies to: 53-55

src/utils/model/openaiModelDiscovery.test.ts (1)

104-113: LGTM!


📝 Walkthrough

Walkthrough

Implements OPENAI_API_KEYS as a comma-separated credential pool for OpenAI-compatible providers. A new CredentialPool class handles cursor-based round-robin lease selection with per-credential cooldown windows and permanent auth-disable state. The OpenAI shim integrates per-attempt credential leasing with auth/cooldown failure classification and retry. Pooled credential awareness is propagated across route metadata, provider validation, gateway/vendor contracts, profile env management, discovery services, cache-probe, model command, CLI scripts (bootstrap/launch/recommend), system diagnostics, and operational tooling (env-files, secret redaction, spawn forwarding).

Changes

OPENAI_API_KEYS credential pool rotation

Layer / File(s) Summary
CredentialPool primitives and parsing helpers
src/services/api/credentialPool.ts, src/services/api/credentialPool.test.ts
Exports CredentialPoolFailureKind, CredentialLease, and CredentialPool class with cursor-based round-robin next(), reportSuccess(), and reportFailure(kind, cooldownMs). Exports parseCredentialList(), firstUsableCredential(), hasUsableOpenAICredential(), and hasInvalidCredentialPlaceholder() helpers for pool validation. Tests cover round-robin selection, auth-based permanent exclusion, cooldown-window skipping, fallback to least-recently-failed, and placeholder rejection.
OpenAI shim per-attempt leasing and retry flow
src/services/api/openaiShim.ts, src/services/api/openaiShim.test.ts, src/services/api/errors.ts, src/services/api/errors.openaiCompatibility.test.ts
Caches CredentialPool parsed from OPENAI_API_KEYS; refactors auth precedence to check OPENAI_API_KEYS pool → OPENAI_API_KEY singular → route credential → xAI OAuth; adds buildHeadersForAttempt(credentialLease) for per-retry auth headers; scales maxAttempts by pool size; leases credential per attempt, reports success/failure to pool with auth vs cooldown classification. Updates auth_invalid error guidance text to mention OPENAI_API_KEYS. Tests verify rotation on HTTP 429, no rotation on 5xx, cooldown persistence, auth-based permanent eviction, Azure api-key and Bankr X-API-Key rotation, provider-flag precedence, and OpenCode retry semantics.
Credential usability helpers and provider intent gating
src/integrations/routeMetadata.ts, src/utils/providerAutoDetect.ts, src/integrations/routeMetadata.test.ts, src/utils/providerAutoDetect.test.ts
Adds hasUsableEnvCredentialValue() and hasAnyUsableOpenAICredential() predicates that reject delimiter-only and SUA_CHAVE placeholder entries. Updates MiniMax/Venice/Xiaomi env-only intent checks to use hasAnyUsableOpenAICredential() instead of checking OPENAI_API_KEY non-emptiness. Updates provider auto-detect to validate OpenAI env vars via usability predicates, ignoring invalid pooled keys during provider selection.
Route credential env-var discovery and precedence ordering
src/integrations/routeMetadata.ts, src/integrations/providerUiMetadata.ts, src/utils/providerProfiles.test.ts
Reorders getRouteCredentialEnvVars() for custom/openai-compatible/local routes to list OPENAI_API_KEYS before OPENAI_API_KEY. Adds hasUsableEnvValue() predicate in provider UI metadata to skip delimiter-only and invalid OpenAI credential values during env-var scanning. Updates provider preset defaults to respect pool precedence when populating credential display. Tests verify pooled-key precedence, fallback-to-singular behavior, and pooled-only route inference.
Provider validation and gateway/vendor credential contracts
src/utils/providerValidation.ts, src/integrations/vendors/openai.ts, src/integrations/gateways/*.ts, src/integrations/vendors/venice.ts, src/integrations/vendors/xiaomi-mimo.ts, src/utils/providerValidation.test.ts
Expands credentialEnvVars in all relevant gateways and vendors to include OPENAI_API_KEYS alongside OPENAI_API_KEY. Introduces hasUsableCredentialEnvValue() and hasOpenAICredential() helpers to centralize credential presence logic. Reworks invalid-credential detection to split comma-delimited env-var values and test configured invalid values against each token. Emits unified "OPENAI_API_KEYS or OPENAI_API_KEY" missing-key guidance. Tests include parameterized matrices validating pooled-key-only scenarios across provider/model combinations.
Profile env pool sanitization and launch-env propagation
src/utils/providerProfile.ts, src/utils/providerProfile.test.ts, src/utils/opencodeProfile.test.ts
Extends ProfileEnv with optional OPENAI_API_KEYS? field; adds to profile cleanup keys. Exports sanitizeOpenAICredentialPool(), hasInvalidOpenAICredentialPool(), and resolveOpenAICredentialEnvState() helpers. Refactors buildOpenAIProfileEnv() to resolve credentials from explicit → pooled → singular sources with invalid-pool short-circuiting, then outputs either OPENAI_API_KEYS (multi-entry) or OPENAI_API_KEY (single) based on usable cardinality. Updates buildLaunchEnv() to clear both env vars for xAI OAuth, and to emit resolved credential via computed env-var name in opencode/default relaunch paths. Tests cover profile switching, xAI OAuth regression, legacy startup rebuilds, and mixed pooled/singular edge cases.
Discovery, cache-probe, runtime limits, and cache-partition keying
src/integrations/discoveryService.ts, src/integrations/runtimeMetadata.ts, src/utils/model/nvidiaNimModels.ts, src/utils/model/openaiModelDiscovery.ts, src/commands/cache-probe/cache-probe.ts, src/services/api/bootstrap.ts, src/services/api/providerConfig.ts, src/commands/model/model.tsx, multiple test files
Exports resolveCacheProbeApiKey() and resolveCacheProbeRequestApiKey() helpers for cache-probe and GitHub Copilot flows. Updates discovery service, runtime metadata, model command, legacy discovery, and local bootstrap to normalize credentials through firstUsableCredential(), skipping invalid placeholders. Introduces getNvidiaNimDiscoveryCacheKeyForEnv() exported helper and refactors NVIDIA NIM model discovery to centralize cache-key derivation. Extends cache-scope hashing to include normalized OPENAI_API_KEYS values. Tests verify discovery with pooled credentials, cache-key parity, multi-path credential normalization, and provider-env-file loading/restoration.
Provider wizard, GitHub onboarding, and manager cleanup
src/commands/provider/provider.tsx, src/commands/onboard-github/onboard-github.tsx, src/components/ProviderManager.tsx, multiple test files
Updates OpenAI provider wizard openai-key step to derive current credential from metadata and validate via sanitizeOpenAICredentialPool(). Extends PROVIDER_SPECIFIC_KEYS to include OPENAI_API_KEYS for GitHub onboarding env patching. Extends GitHub provider activation/deletion to clear OPENAI_API_KEYS in both user settings and process env. Updates saved-profile credential display to check OPENAI_API_KEYS first with sanitizeOpenAICredentialPool(). Tests validate pooled credential redaction and delimiter-only edge cases in profile display.
Bootstrap, launch, and recommend CLI scripts
scripts/provider-bootstrap.ts, scripts/provider-launch.ts, scripts/provider-recommend.ts, scripts/provider-launch.test.ts, scripts/provider-recommend.test.ts
Updates provider-bootstrap to remove process.env.OPENAI_API_KEY fallback and pass only explicit --api-key argument; error guidance mentions both OPENAI_API_KEYS and OPENAI_API_KEY. Introduces hasUsableOpenAILaunchCredential() exported helper in provider-launch, replacing direct env checks with predicate-based credential gating; updates error message. Introduces getOpenAIConfigurationState() exported helper in provider-recommend to resolve { configured, invalid } state; updates OpenAI configuration detection and startup guidance to distinguish invalid vs unset. Changes script entry points to import.meta.main conditional execution. Tests cover pooled credential configuration states and startup guidance variations.
System diagnostics, env-file, secrets, and spawn forwarding
scripts/system-check.ts, scripts/system-check.test.ts, src/utils/diagnostics/issueReport.ts, src/utils/envFile.ts, src/utils/providerSecrets.ts, src/utils/providerStartupOverrides.ts, src/utils/swarm/spawnUtils.ts, src/utils/statusRedaction.test.ts, multiple test files
Adds hasPlaceholderCredential() helper in system-check to detect SUA_CHAVE as individual comma-delimited tokens; updates checkOpenAIEnv() with token-aware placeholder validation across resolved credentials and env-var lists. Updates hasDiagnosticCredentialValue() to parse pools via parseCredentialList() and treat as present only when containing valid entries. Adds OPENAI_API_KEYS to: ALLOWED_ENV_FILE_KEYS (provider env-file allowlist), STARTUP_PROVIDER_OVERRIDE_ENV_KEYS (startup clearing), and TEAMMATE_ENV_VARS (spawn forwarding). Updates providerSecrets to split comma-separated values and add each token as individual secret candidate. Tests verify delimiter-only handling, placeholder detection in pools, env-file loading/restoration, secret extraction/redaction, and cross-test env isolation.
Configuration docs and env example
.env.example, docs/advanced-setup.md
Documents OPENAI_API_KEYS as optional commented entry showing comma-separated credential pool format with rotation guidance. Updates environment variables table with OPENAI_API_KEYS pool behavior, rotation on auth/quota/rate-limit failures, and precedence over OPENAI_API_KEY. Clarifies OPENAI_API_KEY is only required when OPENAI_API_KEYS is unset/empty for non-local cloud routes; explicit exemption for local OpenAI-compatible proxies. Updates provider launch profiles section to document pool/singular fallback behavior.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • Gitlawb/openclaude#1594: Both update src/integrations/routeMetadata.ts credential usability logic that feeds env-only provider routing intent checking.
  • Gitlawb/openclaude#1620: Both modify src/utils/providerProfile.ts buildOpenAIProfileEnv() and launch env logic in related context.
  • Gitlawb/openclaude#1665: Both update scripts/system-check.ts OpenAI credential/SUA_CHAVE detection and resolved-credential context handling.

Suggested reviewers

  • kevincodex1
🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
No Hidden Policy Change ⚠️ Warning Routing-default policy change hidden in cleanup: Venice/Xiaomi-Mimo/MiniMax auto-selection now blocks when OPENAI_API_KEYS exists, but this behavioral change is undisclosed in PR description despit... Add explicit note to PR description: explain that Venice/Xiaomi-Mimo/MiniMax env-only-provider intent gating changed from checking non-empty OPENAI_API_KEY to blocking when any usable OpenAI credential exists (now includes OPENAI_API_KEY...
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title concisely summarizes the main change: adding OpenAI-compatible credential pool failover support.
Description check ✅ Passed Description is comprehensive with clear summary, impact, testing evidence, and provider paths tested. All template sections are well-populated.
Linked Issues check ✅ Passed PR directly implements the core requirement from #901: automatic failover among multiple OpenAI-compatible credentials via comma-separated pools.
Out of Scope Changes check ✅ Passed All changes are scoped to credential pooling infrastructure and environment validation. No unrelated refactoring or scope creep detected.
Risk Surface Disclosed ✅ Passed PR includes explicit "Risk surface" section identifying auth/retry/credential-precedence concerns with documented mitigations and 597 lines of regression test coverage; no blockers flagged.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Treat whitespace-only OPENAI_API_KEY as unset before xAI OAuth fallback.

openAIApiKey is trimmed, but the xAI OAuth gate and final fallback still use raw process.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

📥 Commits

Reviewing files that changed from the base of the PR and between c4aa756 and 9c32008.

📒 Files selected for processing (6)
  • .env.example
  • docs/advanced-setup.md
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.md
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.md
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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 Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.md
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/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.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/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!

@jatmn jatmn self-assigned this Jun 18, 2026
@jatmn jatmn added the enhancement New feature or request label Jun 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9c32008 and 1781d78.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (11)
  • .env.example
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/utils/providerValidation.test.ts
  • src/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.md
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.md
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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 Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.md
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/integrations/vendors/openai.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/utils/providerValidation.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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_KEY rotation 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

Comment thread src/integrations/routeMetadata.test.ts
Comment thread src/services/api/credentialPool.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1781d78 and b43b26a.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (11)
  • .env.example
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • docs/advanced-setup.md
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/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.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • docs/advanced-setup.md
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/openaiShim.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • docs/advanced-setup.md
  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/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

Comment thread src/integrations/vendors/openai.ts
Comment thread src/utils/providerValidation.ts
@jatmn
jatmn force-pushed the issue-901 branch 2 times, most recently from 18d09f5 to 6693d93 Compare June 18, 2026 05:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between b43b26a and 18d09f5.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (11)
  • .env.example
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/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.ts
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.ts
  • src/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/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.ts
  • src/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!

Comment thread src/services/api/openaiShim.test.ts
Comment thread src/services/api/openaiShim.ts Outdated
Comment thread src/services/api/openaiShim.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Add placeholder validation for OPENAI_API_KEYS to match the new accepted credential sources.

Line [33] accepts OPENAI_API_KEYS, but Line [39]-Line [43] only rejects placeholder SUA_CHAVE for OPENAI_API_KEY. This lets OPENAI_API_KEYS=SUA_CHAVE pass 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

📥 Commits

Reviewing files that changed from the base of the PR and between 18d09f5 and 6693d93.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (12)
  • .env.example
  • docs/advanced-setup.md
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/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.ts
  • docs/advanced-setup.md
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • docs/advanced-setup.md
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • docs/advanced-setup.md
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/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 chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • scripts/system-check.test.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/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_KEY validation 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. The openAIApiKeysPoolRaw now validates via parseCredentialList, but openAIApiKey does not. This was flagged in the prior round and the suggested fix was not applied.


2909-2921: Duplicate: singleAuthValue fallback reuses disabled credentials.

The previous review flagged that when all pooled keys are 401-disabled, credentialPool.next() returns null, but authValue falls back to singleAuthValue (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 singleAuthValue fallback 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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Add placeholder-value validation parity for OPENAI_API_KEYS.

invalidCredentialValues only guards OPENAI_API_KEY. With this change, OPENAI_API_KEYS=SUA_CHAVE bypasses 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 win

Fail fast when the credential pool is exhausted.

When credentialPool.next() returns null (all pooled keys disabled), the loop still performs outbound requests with no auth and retries until maxAttempts. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 6693d93 and a6c64e3.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (12)
  • .env.example
  • docs/advanced-setup.md
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/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.ts
  • docs/advanced-setup.md
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/integrations/vendors/openai.ts
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • docs/advanced-setup.md
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • docs/advanced-setup.md
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • src/utils/providerValidation.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/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!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between a6c64e3 and 435e06f.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (12)
  • .env.example
  • docs/advanced-setup.md
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • docs/advanced-setup.md
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • docs/advanced-setup.md
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • docs/advanced-setup.md
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
  • src/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.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/services/api/credentialPool.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/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!

Comment thread docs/advanced-setup.md Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7cee4df and d9ab32c.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (14)
  • .env.example
  • docs/advanced-setup.md
  • scripts/system-check.test.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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.ts
  • src/integrations/vendors/openai.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/openaiShim.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • scripts/system-check.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/integrations/vendors/openai.ts
  • docs/advanced-setup.md
  • src/integrations/routeMetadata.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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 execa for child processes

Files:

  • src/utils/providerProfile.ts
  • src/utils/providerProfile.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerValidation.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/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.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerValidation.test.ts
  • src/utils/providerValidation.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/openaiShim.test.ts
  • src/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!

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
jatmn added 8 commits June 22, 2026 05:45
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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🔴 Critical

Add 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:

  1. Blank submit reusing current pooled/session credentials
  2. Placeholder rejection (SUA_CHAVE) via sanitizeOpenAICredentialPool

Per 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

📥 Commits

Reviewing files that changed from the base of the PR and between 62a8b86 and c2e3bd3.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (64)
  • .env.example
  • docs/advanced-setup.md
  • scripts/provider-bootstrap.ts
  • scripts/provider-launch.ts
  • scripts/provider-recommend.test.ts
  • scripts/provider-recommend.ts
  • scripts/system-check.test.ts
  • scripts/system-check.ts
  • src/commands/cache-probe/cache-probe.test.ts
  • src/commands/cache-probe/cache-probe.ts
  • src/commands/model/model.test.tsx
  • src/commands/model/model.tsx
  • src/commands/onboard-github/onboard-github.test.ts
  • src/commands/onboard-github/onboard-github.tsx
  • src/commands/provider/provider.test.tsx
  • src/commands/provider/provider.tsx
  • src/components/ProviderManager.tsx
  • src/integrations/discoveryService.test.ts
  • src/integrations/discoveryService.ts
  • src/integrations/gateways/custom.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/hicap.ts
  • src/integrations/gateways/opencode-go.ts
  • src/integrations/gateways/opencode.ts
  • src/integrations/providerUiMetadata.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/integrations/runtimeMetadata.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/vendors/venice.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/services/api/bootstrap.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/services/api/errors.openaiCompatibility.test.ts
  • src/services/api/errors.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/services/api/providerConfig.local.test.ts
  • src/services/api/providerConfig.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/utils/envFile.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.test.ts
  • src/utils/providerAutoDetect.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/providerValidation.test.ts
  • src/utils/providerValidation.ts
  • src/utils/statusRedaction.test.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/swarm/spawnUtils.ts
  • src/services/api/errors.ts
  • src/utils/envFile.ts
  • src/utils/providerAutoDetect.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/utils/providerProfiles.test.ts
  • src/commands/model/model.tsx
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/commands/model/model.test.tsx
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/components/ProviderManager.tsx
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/integrations/discoveryService.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/integrations/providerUiMetadata.ts
  • src/utils/statusRedaction.test.ts
  • src/commands/provider/provider.tsx
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/onboard-github/onboard-github.tsx
  • src/commands/cache-probe/cache-probe.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/commands/cache-probe/cache-probe.ts
  • src/utils/providerProfile.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/services/api/errors.openaiCompatibility.test.ts
  • src/services/api/errors.ts
  • src/services/api/providerConfig.local.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/services/api/providerConfig.ts
  • src/services/api/bootstrap.ts
  • src/commands/cache-probe/cache-probe.test.ts
  • src/services/api/openaiShim.test.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/commands/cache-probe/cache-probe.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/services/api/errors.openaiCompatibility.test.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/swarm/spawnUtils.ts
  • src/services/api/errors.ts
  • src/utils/envFile.ts
  • src/utils/providerAutoDetect.test.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/services/api/providerConfig.local.test.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/services/api/providerConfig.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/utils/statusRedaction.test.ts
  • src/services/api/openaiShim.test.ts
  • src/utils/providerValidation.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/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.ts
  • src/services/api/errors.ts
  • src/integrations/runtimeMetadata.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/integrations/discoveryService.ts
  • src/integrations/providerUiMetadata.ts
  • src/integrations/runtimeMetadata.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/swarm/spawnUtils.ts
  • src/services/api/errors.ts
  • src/utils/envFile.ts
  • src/utils/providerAutoDetect.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • scripts/provider-bootstrap.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/utils/providerProfiles.test.ts
  • src/commands/model/model.tsx
  • scripts/system-check.ts
  • scripts/provider-launch.ts
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/commands/model/model.test.tsx
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • scripts/provider-recommend.test.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/components/ProviderManager.tsx
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/integrations/discoveryService.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/integrations/providerUiMetadata.ts
  • src/utils/statusRedaction.test.ts
  • scripts/provider-recommend.ts
  • src/commands/provider/provider.tsx
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/onboard-github/onboard-github.tsx
  • src/commands/cache-probe/cache-probe.test.ts
  • docs/advanced-setup.md
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/commands/cache-probe/cache-probe.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/providerAutoDetect.test.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/opencodeProfile.test.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/commands/model/model.test.tsx
  • scripts/provider-recommend.test.ts
  • src/utils/envFile.test.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/utils/providerValidation.test.ts
  • src/utils/statusRedaction.test.ts
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/cache-probe/cache-probe.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/providerAutoDetect.test.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/opencodeProfile.test.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/commands/model/model.test.tsx
  • scripts/provider-recommend.test.ts
  • src/utils/envFile.test.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/utils/providerValidation.test.ts
  • src/utils/statusRedaction.test.ts
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/cache-probe/cache-probe.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/services/api/credentialPool.test.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/swarm/spawnUtils.ts
  • src/services/api/errors.ts
  • src/utils/envFile.ts
  • src/utils/providerAutoDetect.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • scripts/provider-bootstrap.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/utils/providerProfiles.test.ts
  • src/commands/model/model.tsx
  • scripts/system-check.ts
  • scripts/provider-launch.ts
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/commands/model/model.test.tsx
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • scripts/provider-recommend.test.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/components/ProviderManager.tsx
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/integrations/discoveryService.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/integrations/providerUiMetadata.ts
  • src/utils/statusRedaction.test.ts
  • scripts/provider-recommend.ts
  • src/commands/provider/provider.tsx
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/onboard-github/onboard-github.tsx
  • src/commands/cache-probe/cache-probe.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/commands/cache-probe/cache-probe.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/swarm/spawnUtils.ts
  • src/services/api/errors.ts
  • src/utils/envFile.ts
  • src/utils/providerAutoDetect.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • scripts/provider-bootstrap.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/utils/providerProfiles.test.ts
  • src/commands/model/model.tsx
  • scripts/system-check.ts
  • scripts/provider-launch.ts
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/commands/model/model.test.tsx
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • scripts/provider-recommend.test.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/components/ProviderManager.tsx
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/integrations/discoveryService.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/integrations/providerUiMetadata.ts
  • src/utils/statusRedaction.test.ts
  • scripts/provider-recommend.ts
  • src/commands/provider/provider.tsx
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/onboard-github/onboard-github.tsx
  • src/commands/cache-probe/cache-probe.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/commands/cache-probe/cache-probe.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/swarm/spawnUtils.ts
  • src/services/api/errors.ts
  • src/utils/envFile.ts
  • src/utils/providerAutoDetect.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • scripts/provider-bootstrap.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/utils/providerProfiles.test.ts
  • src/commands/model/model.tsx
  • scripts/system-check.ts
  • scripts/provider-launch.ts
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/commands/model/model.test.tsx
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • scripts/provider-recommend.test.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/components/ProviderManager.tsx
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/integrations/discoveryService.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/integrations/providerUiMetadata.ts
  • src/utils/statusRedaction.test.ts
  • scripts/provider-recommend.ts
  • src/commands/provider/provider.tsx
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/onboard-github/onboard-github.tsx
  • src/commands/cache-probe/cache-probe.test.ts
  • docs/advanced-setup.md
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/commands/cache-probe/cache-probe.ts
  • src/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.ts
  • src/utils/providerSecrets.test.ts
  • src/services/api/errors.ts
  • src/utils/providerAutoDetect.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/utils/providerStartupOverrides.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/integrations/discoveryService.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/integrations/providerUiMetadata.ts
  • src/commands/provider/provider.tsx
  • src/integrations/runtimeMetadata.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/providerAutoDetect.test.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/opencodeProfile.test.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/commands/model/model.test.tsx
  • scripts/provider-recommend.test.ts
  • src/utils/envFile.test.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/utils/providerValidation.test.ts
  • src/utils/statusRedaction.test.ts
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/cache-probe/cache-probe.test.ts
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/services/api/credentialPool.test.ts
  • src/utils/providerProfile.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • src/utils/diagnostics/issueReport.test.ts
  • src/utils/providerSecrets.test.ts
  • src/utils/swarm/spawnUtils.ts
  • src/services/api/errors.ts
  • src/utils/envFile.ts
  • src/utils/providerAutoDetect.test.ts
  • src/integrations/runtimeMetadata.ts
  • src/utils/providerStartupOverrides.ts
  • src/utils/swarm/spawnUtils.test.ts
  • src/integrations/vendors/venice.ts
  • src/services/api/providerConfig.local.test.ts
  • scripts/system-check.test.ts
  • src/commands/onboard-github/onboard-github.test.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • scripts/provider-bootstrap.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/utils/providerProfiles.test.ts
  • src/commands/model/model.tsx
  • scripts/system-check.ts
  • scripts/provider-launch.ts
  • src/utils/opencodeProfile.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/integrations/routeMetadata.test.ts
  • src/utils/model/nvidiaNimModels.ts
  • src/commands/model/model.test.tsx
  • src/integrations/gateways/opencode.ts
  • src/services/api/providerConfig.ts
  • src/integrations/vendors/openai.ts
  • scripts/provider-recommend.test.ts
  • src/utils/diagnostics/issueReport.ts
  • src/utils/envFile.test.ts
  • src/components/ProviderManager.tsx
  • src/integrations/gateways/opencode-go.ts
  • src/services/api/bootstrap.ts
  • src/utils/model/nvidiaNimModels.test.ts
  • src/utils/model/openaiModelDiscovery.test.ts
  • src/integrations/discoveryService.ts
  • src/utils/providerValidation.test.ts
  • src/utils/model/openaiModelDiscovery.ts
  • src/integrations/providerUiMetadata.ts
  • src/utils/statusRedaction.test.ts
  • scripts/provider-recommend.ts
  • src/commands/provider/provider.tsx
  • src/integrations/runtimeMetadata.test.ts
  • src/commands/onboard-github/onboard-github.tsx
  • src/commands/cache-probe/cache-probe.test.ts
  • docs/advanced-setup.md
  • src/services/api/openaiShim.test.ts
  • src/integrations/discoveryService.test.ts
  • src/utils/providerValidation.ts
  • src/integrations/routeMetadata.ts
  • src/services/api/openaiShim.ts
  • src/services/api/credentialPool.test.ts
  • src/services/api/credentialPool.ts
  • src/utils/providerProfile.ts
  • src/commands/cache-probe/cache-probe.ts
  • src/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.ts
  • src/utils/providerAutoDetect.test.ts
  • src/utils/providerStartupOverrides.ts
  • src/services/api/providerConfig.local.test.ts
  • src/utils/providerSecrets.ts
  • src/utils/providerStartupOverrides.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerAutoDetect.ts
  • src/commands/provider/provider.test.tsx
  • src/services/api/providerConfig.ts
  • src/utils/providerValidation.test.ts
  • src/integrations/providerUiMetadata.ts
  • src/commands/provider/provider.tsx
  • src/utils/providerValidation.ts
  • src/utils/providerProfile.ts
  • src/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.ts
  • src/integrations/vendors/venice.ts
  • src/integrations/vendors/xiaomi-mimo.ts
  • src/integrations/gateways/hicap.ts
  • src/integrations/gateways/gitlawb-opengateway.ts
  • src/integrations/gateways/custom.ts
  • src/integrations/routeMetadata.test.ts
  • src/integrations/gateways/opencode.ts
  • src/integrations/vendors/openai.ts
  • src/integrations/gateways/opencode-go.ts
  • src/integrations/discoveryService.ts
  • src/integrations/providerUiMetadata.ts
  • src/integrations/runtimeMetadata.test.ts
  • src/integrations/discoveryService.test.ts
  • src/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.ts
  • scripts/provider-bootstrap.ts
  • scripts/system-check.ts
  • scripts/provider-launch.ts
  • scripts/provider-recommend.test.ts
  • scripts/provider-recommend.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander for CLI argument parsing

Files:

  • src/commands/onboard-github/onboard-github.test.ts
  • src/commands/cache-probe/cache-probe.test.ts
  • src/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

Comment thread src/integrations/routeMetadata.test.ts
Comment thread src/utils/providerValidation.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between f582073 and c349902.

📒 Files selected for processing (2)
  • src/integrations/routeMetadata.test.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for 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.ts
  • src/integrations/routeMetadata.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/utils/model/openaiModelDiscovery.ts
  • src/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.ts
  • src/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.ts
  • src/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.ts
  • src/integrations/routeMetadata.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This 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:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for 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.ts
  • src/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

Comment thread src/utils/model/openaiModelDiscovery.ts Outdated
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":500,"request":{"method":"PATCH","url":"https://api.github.com/repos/Gitlawb/openclaude/issues/comments/4737614692","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- review_stack_entry_start -->\n\n[![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/Gitlawb/openclaude/pull/1706?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)\n\n<!-- review_stack_entry_end -->\n<!-- This is an auto-generated comment: review in progress by coderabbit.ai -->\n\n> [!NOTE]\n> Currently processing new changes in this PR. This may take a few minutes, please wait...\n> \n> <details>\n> <summary>⚙️ Run configuration</summary>\n> \n> **Configuration used**: Path: .coderabbit.yaml\n> \n> **Review profile**: ASSERTIVE\n> \n> **Plan**: Pro Plus\n> \n> **Run ID**: `81726511-b738-44f0-acab-ac08a46f9cdb`\n> \n> </details>\n> \n> <details>\n> <summary>📥 Commits</summary>\n> \n> Reviewing files that changed from the base of the PR and between c349902ffa080d3603a1e5397cfbeeb08f212d8a and ecdf8858a77ccf2dd5968235ee6f3980fa0846c4.\n> \n> </details>\n> \n> <details>\n> <summary>📒 Files selected for processing (2)</summary>\n> \n> * `src/utils/model/openaiModelDiscovery.test.ts`\n> * `src/utils/model/openaiModelDiscovery.ts`\n> \n> </details>\n> \n> \n\n<!-- end of auto-generated comment: review in progress by coderabbit.ai -->\n\n<!-- walkthrough_start -->\n\n<details>\n<summary>📝 Walkthrough</summary>\n\n## Walkthrough\n\nImplements `OPENAI_API_KEYS` as a comma-separated credential pool for OpenAI-compatible providers. A new `CredentialPool` class handles cursor-based round-robin lease selection with per-credential cooldown windows and permanent auth-disable state. The OpenAI shim integrates per-attempt credential leasing with auth/cooldown failure classification and retry. Pooled credential awareness is propagated across route metadata, provider validation, gateway/vendor contracts, profile env management, discovery services, cache-probe, model command, CLI scripts (bootstrap/launch/recommend), system diagnostics, and operational tooling (env-files, secret redaction, spawn forwarding).\n\n## Changes\n\n**OPENAI_API_KEYS credential pool rotation**\n\n| Layer / File(s) | Summary |\n|---|---|\n| **CredentialPool primitives and parsing helpers** <br> `src/services/api/credentialPool.ts`, `src/services/api/credentialPool.test.ts` | Exports `CredentialPoolFailureKind`, `CredentialLease`, and `CredentialPool` class with cursor-based round-robin `next()`, `reportSuccess()`, and `reportFailure(kind, cooldownMs)`. Exports `parseCredentialList()`, `firstUsableCredential()`, `hasUsableOpenAICredential()`, and `hasInvalidCredentialPlaceholder()` helpers for pool validation. Tests cover round-robin selection, auth-based permanent exclusion, cooldown-window skipping, fallback to least-recently-failed, and placeholder rejection. |\n| **OpenAI shim per-attempt leasing and retry flow** <br> `src/services/api/openaiShim.ts`, `src/services/api/openaiShim.test.ts`, `src/services/api/errors.ts`, `src/services/api/errors.openaiCompatibility.test.ts` | Caches `CredentialPool` parsed from `OPENAI_API_KEYS`; refactors auth precedence to check `OPENAI_API_KEYS` pool → `OPENAI_API_KEY` singular → route credential → xAI OAuth; adds `buildHeadersForAttempt(credentialLease)` for per-retry auth headers; scales `maxAttempts` by pool size; leases credential per attempt, reports success/failure to pool with auth vs cooldown classification. Updates `auth_invalid` error guidance text to mention `OPENAI_API_KEYS`. Tests verify rotation on HTTP 429, no rotation on 5xx, cooldown persistence, auth-based permanent eviction, Azure api-key and Bankr X-API-Key rotation, provider-flag precedence, and OpenCode retry semantics. |\n| **Credential usability helpers and provider intent gating** <br> `src/integrations/routeMetadata.ts`, `src/utils/providerAutoDetect.ts`, `src/integrations/routeMetadata.test.ts`, `src/utils/providerAutoDetect.test.ts` | Adds `hasUsableEnvCredentialValue()` and `hasAnyUsableOpenAICredential()` predicates that reject delimiter-only and `SUA_CHAVE` placeholder entries. Updates MiniMax/Venice/Xiaomi env-only intent checks to use `hasAnyUsableOpenAICredential()` instead of checking `OPENAI_API_KEY` non-emptiness. Updates provider auto-detect to validate OpenAI env vars via usability predicates, ignoring invalid pooled keys during provider selection. |\n| **Route credential env-var discovery and precedence ordering** <br> `src/integrations/routeMetadata.ts`, `src/integrations/providerUiMetadata.ts`, `src/utils/providerProfiles.test.ts` | Reorders `getRouteCredentialEnvVars()` for custom/openai-compatible/local routes to list `OPENAI_API_KEYS` before `OPENAI_API_KEY`. Adds `hasUsableEnvValue()` predicate in provider UI metadata to skip delimiter-only and invalid OpenAI credential values during env-var scanning. Updates provider preset defaults to respect pool precedence when populating credential display. Tests verify pooled-key precedence, fallback-to-singular behavior, and pooled-only route inference. |\n| **Provider validation and gateway/vendor credential contracts** <br> `src/utils/providerValidation.ts`, `src/integrations/vendors/openai.ts`, `src/integrations/gateways/*.ts`, `src/integrations/vendors/venice.ts`, `src/integrations/vendors/xiaomi-mimo.ts`, `src/utils/providerValidation.test.ts` | Expands `credentialEnvVars` in all relevant gateways and vendors to include `OPENAI_API_KEYS` alongside `OPENAI_API_KEY`. Introduces `hasUsableCredentialEnvValue()` and `hasOpenAICredential()` helpers to centralize credential presence logic. Reworks invalid-credential detection to split comma-delimited env-var values and test configured invalid values against each token. Emits unified \"OPENAI_API_KEYS or OPENAI_API_KEY\" missing-key guidance. Tests include parameterized matrices validating pooled-key-only scenarios across provider/model combinations. |\n| **Profile env pool sanitization and launch-env propagation** <br> `src/utils/providerProfile.ts`, `src/utils/providerProfile.test.ts`, `src/utils/opencodeProfile.test.ts` | Extends `ProfileEnv` with optional `OPENAI_API_KEYS?` field; adds to profile cleanup keys. Exports `sanitizeOpenAICredentialPool()`, `hasInvalidOpenAICredentialPool()`, and `resolveOpenAICredentialEnvState()` helpers. Refactors `buildOpenAIProfileEnv()` to resolve credentials from explicit → pooled → singular sources with invalid-pool short-circuiting, then outputs either `OPENAI_API_KEYS` (multi-entry) or `OPENAI_API_KEY` (single) based on usable cardinality. Updates `buildLaunchEnv()` to clear both env vars for xAI OAuth, and to emit resolved credential via computed env-var name in opencode/default relaunch paths. Tests cover profile switching, xAI OAuth regression, legacy startup rebuilds, and mixed pooled/singular edge cases. |\n| **Discovery, cache-probe, runtime limits, and cache-partition keying** <br> `src/integrations/discoveryService.ts`, `src/integrations/runtimeMetadata.ts`, `src/utils/model/nvidiaNimModels.ts`, `src/utils/model/openaiModelDiscovery.ts`, `src/commands/cache-probe/cache-probe.ts`, `src/services/api/bootstrap.ts`, `src/services/api/providerConfig.ts`, `src/commands/model/model.tsx`, multiple test files | Exports `resolveCacheProbeApiKey()` and `resolveCacheProbeRequestApiKey()` helpers for cache-probe and GitHub Copilot flows. Updates discovery service, runtime metadata, model command, legacy discovery, and local bootstrap to normalize credentials through `firstUsableCredential()`, skipping invalid placeholders. Introduces `getNvidiaNimDiscoveryCacheKeyForEnv()` exported helper and refactors NVIDIA NIM model discovery to centralize cache-key derivation. Extends cache-scope hashing to include normalized `OPENAI_API_KEYS` values. Tests verify discovery with pooled credentials, cache-key parity, multi-path credential normalization, and provider-env-file loading/restoration. |\n| **Provider wizard, GitHub onboarding, and manager cleanup** <br> `src/commands/provider/provider.tsx`, `src/commands/onboard-github/onboard-github.tsx`, `src/components/ProviderManager.tsx`, multiple test files | Updates OpenAI provider wizard openai-key step to derive current credential from metadata and validate via `sanitizeOpenAICredentialPool()`. Extends `PROVIDER_SPECIFIC_KEYS` to include `OPENAI_API_KEYS` for GitHub onboarding env patching. Extends GitHub provider activation/deletion to clear `OPENAI_API_KEYS` in both user settings and process env. Updates saved-profile credential display to check `OPENAI_API_KEYS` first with `sanitizeOpenAICredentialPool()`. Tests validate pooled credential redaction and delimiter-only edge cases in profile display. |\n| **Bootstrap, launch, and recommend CLI scripts** <br> `scripts/provider-bootstrap.ts`, `scripts/provider-launch.ts`, `scripts/provider-recommend.ts`, `scripts/provider-launch.test.ts`, `scripts/provider-recommend.test.ts` | Updates provider-bootstrap to remove `process.env.OPENAI_API_KEY` fallback and pass only explicit `--api-key` argument; error guidance mentions both `OPENAI_API_KEYS` and `OPENAI_API_KEY`. Introduces `hasUsableOpenAILaunchCredential()` exported helper in provider-launch, replacing direct env checks with predicate-based credential gating; updates error message. Introduces `getOpenAIConfigurationState()` exported helper in provider-recommend to resolve `{ configured, invalid }` state; updates OpenAI configuration detection and startup guidance to distinguish invalid vs unset. Changes script entry points to `import.meta.main` conditional execution. Tests cover pooled credential configuration states and startup guidance variations. |\n| **System diagnostics, env-file, secrets, and spawn forwarding** <br> `scripts/system-check.ts`, `scripts/system-check.test.ts`, `src/utils/diagnostics/issueReport.ts`, `src/utils/envFile.ts`, `src/utils/providerSecrets.ts`, `src/utils/providerStartupOverrides.ts`, `src/utils/swarm/spawnUtils.ts`, `src/utils/statusRedaction.test.ts`, multiple test files | Adds `hasPlaceholderCredential()` helper in system-check to detect `SUA_CHAVE` as individual comma-delimited tokens; updates `checkOpenAIEnv()` with token-aware placeholder validation across resolved credentials and env-var lists. Updates `hasDiagnosticCredentialValue()` to parse pools via `parseCredentialList()` and treat as present only when containing valid entries. Adds `OPENAI_API_KEYS` to: `ALLOWED_ENV_FILE_KEYS` (provider env-file allowlist), `STARTUP_PROVIDER_OVERRIDE_ENV_KEYS` (startup clearing), and `TEAMMATE_ENV_VARS` (spawn forwarding). Updates providerSecrets to split comma-separated values and add each token as individual secret candidate. Tests verify delimiter-only handling, placeholder detection in pools, env-file loading/restoration, secret extraction/redaction, and cross-test env isolation. |\n| **Configuration docs and env example** <br> `.env.example`, `docs/advanced-setup.md` | Documents `OPENAI_API_KEYS` as optional commented entry showing comma-separated credential pool format with rotation guidance. Updates environment variables table with `OPENAI_API_KEYS` pool behavior, rotation on auth/quota/rate-limit failures, and precedence over `OPENAI_API_KEY`. Clarifies `OPENAI_API_KEY` is only required when `OPENAI_API_KEYS` is unset/empty for non-local cloud routes; explicit exemption for local OpenAI-compatible proxies. Updates provider launch profiles section to document pool/singular fallback behavior. |\n\n## Estimated code review effort\n\n🎯 5 (Critical) | ⏱️ ~120 minutes\n\n## Possibly related PRs\n\n- [Gitlawb/openclaude#1594](https://github.com/Gitlawb/openclaude/pull/1594): Both update `src/integrations/routeMetadata.ts` credential usability logic that feeds env-only provider routing intent checking.\n- [Gitlawb/openclaude#1620](https://github.com/Gitlawb/openclaude/pull/1620): Both modify `src/utils/providerProfile.ts` `buildOpenAIProfileEnv()` and launch env logic in related context.\n- [Gitlawb/openclaude#1665](https://github.com/Gitlawb/openclaude/pull/1665): Both update `scripts/system-check.ts` OpenAI credential/`SUA_CHAVE` detection and resolved-credential context handling.\n\n## Suggested reviewers\n\n- kevincodex1\n\n</details>\n\n<!-- walkthrough_end -->\n<!-- pre_merge_checks_walkthrough_start -->\n\n<details>\n<summary>🚥 Pre-merge checks | ✅ 4 | ❌ 3</summary>\n\n### ❌ Failed checks (3 warnings)\n\n|        Check name       | Status     | Explanation                                                                                                                                                                     | Resolution                                                                                                                                                                                                                         |\n| :---------------------: | :--------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|    Docstring Coverage   | ⚠️ Warning | Docstring coverage is 2.33% which is insufficient. The required threshold is 80.00%.                                                                                            | Write docstrings for the functions missing them to satisfy the coverage threshold.                                                                                                                                                 |\n|  Risk Surface Disclosed | ⚠️ Warning | PR touches auth/provider routing/outbound behavior; PR author disclosed risk surface, but review comments lack explicit risk assessment or blocker determination from reviewer. | Reviewer should explicitly assess and document whether credential precedence, retry classification, and per-attempt auth header changes introduce blockers, and confirm the implementation strategy is acceptable before approval. |\n| No Hidden Policy Change | ⚠️ Warning | Unresolved review comment: openaiModelDiscovery.ts blocks valid OPENAI_API_KEY fallback when OPENAI_API_KEYS contains placeholders, missing requested regression test coverage. | Apply suggested fix to simplify apiKey logic and add regression test for OPENAI_API_KEYS='sk-openai-a,SUA_CHAVE' + valid OPENAI_API_KEY scenario per review instructions.                                                          |\n\n<details>\n<summary>✅ Passed checks (4 passed)</summary>\n\n|         Check name         | Status   | Explanation                                                                                                                                                              |\n| :------------------------: | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|         Title check        | ✅ Passed | Title accurately describes the main change: adding OpenAI-compatible credential pool failover functionality.                                                             |\n|      Description check     | ✅ Passed | PR description is comprehensive, covering summary, impact, risk analysis, testing validation, and provider paths tested; all required sections are present and detailed. |\n|     Linked Issues check    | ✅ Passed | Code changes comprehensively implement issue `#901`'s credential pool failover with automatic rotation on auth/quota/rate-limit failures across multiple API keys.         |\n| Out of Scope Changes check | ✅ Passed | All changes are scoped to OpenAI-compatible credential pooling; multi-Codex OAuth and auth.json pooling explicitly remain out of scope as noted in PR description.       |\n\n</details>\n\n<sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub>\n\n</details>\n\n<!-- pre_merge_checks_walkthrough_end -->\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Gitlawb/openclaude&utm_content=1706)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->"},"request":{"retryCount":3,"signal":{},"retries":3,"retryAfter":16}}}

@jatmn

jatmn commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@kevincodex1

@kevincodex1 kevincodex1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kevincodex1
kevincodex1 merged commit dd4c4ab into Twigpine:main Jun 23, 2026
4 checks passed
@jatmn
jatmn deleted the issue-901 branch June 23, 2026 04:38
0xfandom added a commit to 0xfandom/openclaude that referenced this pull request Jun 23, 2026
…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.
0xfandom added a commit to 0xfandom/openclaude that referenced this pull request Jun 25, 2026
…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.
0xfandom added a commit to 0xfandom/openclaude that referenced this pull request Jun 26, 2026
…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.
0xfandom added a commit to 0xfandom/openclaude that referenced this pull request Jun 29, 2026
…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.
kevincodex1 pushed a commit that referenced this pull request Jul 7, 2026
… 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multiple Codex or other custom provider support

2 participants