Skip to content

feat(providers): add LLMTR Turkey-hosted gateway - #1634

Closed
knowhycodata wants to merge 12 commits into
Twigpine:mainfrom
knowhycodata:feat/add-llmtr-provider
Closed

knowhycodata wants to merge 12 commits into
Twigpine:mainfrom
knowhycodata:feat/add-llmtr-provider

Conversation

@knowhycodata

@knowhycodata knowhycodata commented Jun 14, 2026 •

Copy link
Copy Markdown

Summary

Adds LLMTR (https://llmtr.com) as a global, first-class OpenAI-compatible aggregating provider. LLMTR is a Turkey-hosted AI gateway that exposes a single OpenAI-compatible /v1 endpoint over many upstream providers (OpenAI, Anthropic, Google, xAI, Mistral, …) and additionally serves Turkey-hosted models that run on LLMTR's own infrastructure.

This follows the existing descriptor-based provider pattern (closest reference: hicap).

Changes

  • New gateway descriptor src/integrations/gateways/llmtr.ts
    • id: llmtr, category: aggregating
    • Base URL https://llmtr.com/v1, api-key auth via LLMTR_API_KEY
    • Default model llmtr/gemma-4; OpenAI-compatible model discovery (/models)
    • Credential-env validation matching llmtr.com
  • Seed catalog + shared model descriptors for Turkey-hosted models (Gemma 4, Trendyol 7B, Sincap, Magibu 11B v8) added to openai-compatible-alias.ts
  • Regenerated integrationArtifacts.generated.ts via bun run integrations:generate
  • Registered preset in compatibility.test.ts
  • Docs: README provider table, .env.example block, and web/src/data/providers.ts

Configuration

LLMTR_API_KEY=your-llmtr-key-here
OPENAI_BASE_URL=https://llmtr.com/v1
OPENAI_MODEL=llmtr/gemma-4   # or llmtr/trendyol-7b, llmtr/sincap, llmtr/magibu-11b-v8

Or pick it interactively via /provider.

Testing

  • bun run integrations:check — artifacts up to date
  • bun test src/integrations/ — 184 pass
  • bun run typecheck — clean
  • bun run deadcode (knip) — no new issues

Summary by CodeRabbit

Release Notes

  • New Features
    • Added LLMTR as a Turkey-hosted OpenAI-compatible provider/gateway, with LLMTR_API_KEY support, model routing via OPENAI_MODEL, and included model options.
  • Documentation
    • Updated the “Supported Providers” guide and the example environment file with LLMTR setup and required configuration.
  • Bug Fixes
    • Improved provider-profile persistence and startup env propagation so LLMTR_API_KEY is correctly retained and mirrored for LLMTR-compatible OpenAI routing.
  • Tests
    • Expanded compatibility, profile, and env-alignment coverage for the new LLMTR preset and routing behavior.

Add LLMTR (https://llmtr.com) as a global OpenAI-compatible aggregating
provider. LLMTR is a Turkey-hosted AI gateway exposing a single
OpenAI-compatible /v1 endpoint over many upstream providers, including
Turkey-hosted models that run on LLMTR infrastructure.

- New gateway descriptor at src/integrations/gateways/llmtr.ts
  (api-key auth via LLMTR_API_KEY, base URL https://llmtr.com/v1,
  default model llmtr/gemma-4, OpenAI-compatible model discovery)
- Seed catalog with Turkey-hosted models (Gemma 4, Trendyol 7B, Sincap,
  Magibu 11B v8) and matching shared model descriptors in
  openai-compatible-alias.ts
- Regenerate integration artifacts; register preset in compatibility test
- Document in README provider table, .env.example, and web providers list
@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds LLMTR as a new OpenAI-compatible gateway targeting https://llmtr.com/v1. The integration covers URL validation helper, gateway definition with auth/transport/validation, ProfileEnv type support, a buildLlmtrProfileEnv helper, provider profile system wiring with credential carryover, model aliases, and matching documentation.

Changes

LLMTR Provider Integration

Layer / File(s) Summary
Route metadata URL validation helper
src/integrations/routeMetadata.ts, src/integrations/routeMetadata.test.ts
New exported isLlmtrBaseUrl function validates URLs against llmtr.com hostname by parsing and matching exact domain, returning false for invalid/empty input. Tests verify correct matching and rejection of lookalike hosts.
Gateway definition and model aliases
src/integrations/gateways/llmtr.ts, src/integrations/models/openai-compatible-alias.ts, src/integrations/compatibility.test.ts
Defines the llmtr gateway with OpenAI-compatible transport, LLMTR_API_KEY-only auth, host validation, openai-compatible-models readiness probe, and a four-model hybrid catalog with 1d cache. Extends aliasModels with LLMTR model metadata and registers llmtr in EXPECTED_PRESETS.
ProfileEnv type, buildLlmtrProfileEnv helper, and credential carryover
src/utils/providerProfile.ts, src/utils/providerProfile.test.ts
Extends ProfileEnv with optional LLMTR_API_KEY, adds it to the managed key list, exports buildLlmtrProfileEnv to construct profile env from the API key with route-default base URL/model derivation, and updates buildLaunchEnv to carry over LLMTR_API_KEY from shell or persisted profile. Tests cover persisted and live key prioritization across restarts.
Provider profile system integration and startup
src/utils/providerProfiles.ts, src/utils/providerProfiles.test.ts
Imports buildLlmtrProfileEnv and isLlmtrBaseUrl, wires LLMTR_API_KEY into environment alignment checks, applyProviderProfileToProcessEnv, both startup env builder paths, and buildStartupProfileFromActiveProfile. Tests verify env routing, non-mirroring of non-llmtr profiles, env-drift recovery, and persistence of LLMTR_API_KEY for llmtr-gateway and llmtr.com-targeted OpenAI profiles.
Web UI, docs, and config
web/src/data/providers.ts, README.md, .env.example, src/components/ProviderManager.test.tsx, src/utils/providerSecrets.test.ts
Adds LLMTR to the providers array with setup/notes, documents it in the README supported-providers table and .env.example, adds LLMTR to the PRESET_ORDER in the ProviderManager test, and extends providerSecrets.test.ts to verify LLMTR_API_KEY coverage in the known provider secret env keys set.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Gitlawb/openclaude#1585: Extends identical OpenAI-compatible profile plumbing (providerProfile.ts/providerProfiles.ts) to add a different dedicated-vendor key (ATLAS_CLOUD_API_KEY) with the same structural pattern.
  • Gitlawb/openclaude#1590: Follows the same pattern of adding a new OpenAI-compat provider with dedicated credential mirroring through the same profile/env routing files.
  • Gitlawb/openclaude#1594: Extends the same OpenAI-compatible provider-routing/env-alignment code paths for a different provider (nearai).

Suggested reviewers

  • jatmn
  • kevincodex1
🚥 Pre-merge checks | ✅ 6 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly and concisely describes the main change: adding a new LLMTR provider gateway. It is scoped, specific, and accurately reflects the changeset.
Description check ✅ Passed Description comprehensively covers all required sections with clear context: Summary explains what/why, Changes lists all modifications, Configuration shows usage, and Testing documents validation. All critical information is present.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Risk Surface Disclosed ✅ Passed PR properly discloses and mitigates risk surfaces: credential isolation via dedicatedCredentialsOnly, exact hostname validation preventing lookalike hosts, secret redaction integration, dual-path s...
No Hidden Policy Change ✅ Passed All policy changes verified as explicit and documented. Product defaults, routing logic, telemetry, and permission policies remain unchanged. LLMTR's dedicatedCredentialsOnly trust-model decision i...

✏️ 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

🤖 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/gateways/llmtr.ts`:
- Around line 10-14: The LLMTR gateway configuration in the setup block lacks
the `dedicatedCredentialsOnly: true` flag, and there is a fallback to
`OPENAI_API_KEY` at another location that allows credential reuse. This creates
a security issue where the wrong credential could be sent to llmtr.com. Add
`dedicatedCredentialsOnly: true` to the setup object in the llmtr gateway
configuration (around lines 10-14), and remove the `OPENAI_API_KEY` fallback
from the credential chain (around lines 31-39) to ensure only the dedicated
`LLMTR_API_KEY` can be used for this provider. This prevents unintended
credential leakage between providers.
🪄 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: b072fc14-3b92-4091-8331-3ebedf4e5ecd

📥 Commits

Reviewing files that changed from the base of the PR and between de726c4 and 7b97272.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (6)
  • .env.example
  • README.md
  • src/integrations/compatibility.test.ts
  • src/integrations/gateways/llmtr.ts
  • src/integrations/models/openai-compatible-alias.ts
  • web/src/data/providers.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx,js,jsx,py}: Follow the existing code style in the touched files
Keep comments useful and concise

Files:

  • src/integrations/compatibility.test.ts
  • src/integrations/models/openai-compatible-alias.ts
  • web/src/data/providers.ts
  • src/integrations/gateways/llmtr.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Typecheck TypeScript code before submitting (use bun run typecheck)

Files:

  • src/integrations/compatibility.test.ts
  • src/integrations/models/openai-compatible-alias.ts
  • web/src/data/providers.ts
  • src/integrations/gateways/llmtr.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/compatibility.test.ts
  • src/integrations/models/openai-compatible-alias.ts
  • README.md
  • web/src/data/providers.ts
  • src/integrations/gateways/llmtr.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/compatibility.test.ts
  • src/integrations/models/openai-compatible-alias.ts
  • src/integrations/gateways/llmtr.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/compatibility.test.ts
**

⚙️ CodeRabbit configuration file

**: # Contributing to OpenClaude

Thanks for contributing.

OpenClaude is a fast-moving open-source coding-agent CLI with support for multiple providers, local backends, MCP, and a terminal-first workflow. The best contributions here are focused, well-tested, and easy to review.

Before You Start

  • Search existing issues and discussions before opening a new thread.
  • Check open pull requests for work that overlaps with your contribution. If a PR already exists that addresses the same change, open an issue or discussion first to align on direction — duplicate PRs may be closed without review.
  • Use issues for confirmed bugs and actionable feature work.
  • Use discussions for setup help, ideas, and general community conversation.
  • For larger changes, open an issue first so the scope is clear before implementation.
  • For security reports, follow SECURITY.md.

Pull Requests

Every PR needs a reason. Your PR description must include:

  • what changed and why
  • the user or developer impact
  • the exact checks you ran
  • a linked issue when one exists, using Fixes #123, `Closes `#123, or another clear link
  • screenshots when the PR touches UI, terminal presentation, or the VS Code extension
  • which provider path was tested when the PR changes provider behavior

The PR author is responsible for ensuring their PR is merge-ready. PRs with merge conflicts will not be reviewed or approved until the conflicts are resolved.

Issues are the recommended starting point for anything non-trivial — opening one first helps avoid wasted effort if the change is out of scope or already being worked on. Small fixes, doc corrections, and obvious improvements can stand on their own without a linked issue, as long as the PR description explains the intent.

What Gets Closed Without Review

PRs may be closed without review...

Files:

  • src/integrations/compatibility.test.ts
  • src/integrations/models/openai-compatible-alias.ts
  • README.md
  • web/src/data/providers.ts
  • src/integrations/gateways/llmtr.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:

  • README.md
**/*provider*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Review provider documentation in docs/integrations/overview.md and follow documented patterns in docs/integrations/how-to/ when contributing provider changes

Files:

  • web/src/data/providers.ts
web/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run web typecheck and build checks (bun run web:typecheck and bun run web:build) when touching web/ directory

Files:

  • web/src/data/providers.ts

⚙️ CodeRabbit configuration file

web/**: Review browser extension changes for content-script isolation, message validation, cross-origin assumptions, permission surfaces, and failures that could leak prompts or credentials.

Files:

  • web/src/data/providers.ts
🔇 Additional comments (5)
src/integrations/models/openai-compatible-alias.ts (1)

127-131: LGTM!

src/integrations/compatibility.test.ts (1)

30-30: LGTM!

web/src/data/providers.ts (1)

92-98: LGTM!

README.md (1)

166-166: LGTM!

.env.example (1)

183-189: LGTM!

Comment thread src/integrations/gateways/llmtr.ts
Set dedicatedCredentialsOnly and drop the OPENAI_API_KEY fallback so a
generic OpenAI key is never sent to llmtr.com. Mirrors the atlas-cloud
dedicated-gateway pattern. Addresses PR review feedback.
@knowhycodata

Copy link
Copy Markdown
Author

Addressed the CodeRabbit review finding in a42bf5b: the LLMTR gateway now sets dedicatedCredentialsOnly: true and no longer accepts OPENAI_API_KEY as a fallback, so a generic OpenAI credential can never be sent to llmtr.com. This mirrors the existing atlas-cloud dedicated-gateway pattern.

Verified live against the LLMTR API: /v1/models (HTTP 200, Turkey-hosted models present) and end-to-end through the OpenClaude CLI with only LLMTR_API_KEY set (default llmtr/gemma-4 and Turkey-hosted llmtr/sincap). Integrations tests (184 pass), typecheck, and knip are all green.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I found one issue that needs to be addressed before this is ready.

Findings

  • [P1] Mirror the saved LLMTR key into LLMTR_API_KEY
    src/integrations/gateways/llmtr.ts:16
    Marking this route as dedicatedCredentialsOnly means validation and credential resolution intentionally ignore OPENAI_API_KEY; getRouteCredentialEnvVars('llmtr') returns only LLMTR_API_KEY. However, the /provider profile path still treats new OpenAI-compatible presets like generic OpenAI profiles: applyProviderProfileToProcessEnv and startup profile persistence mirror saved keys for Atlas, NEAR, Fireworks, Venice, MiMo, etc., but there is no LLMTR mirror. A user who picks LLMTR via /provider and enters an API key therefore gets an env/profile with OPENAI_API_KEY and OPENAI_BASE_URL=https://llmtr.com/v1, but no LLMTR_API_KEY, so route validation reports LLMTR auth is required and the saved profile relaunches unauthenticated. Please add LLMTR to the dedicated-key profile env/persistence/cleanup/type surfaces, and cover the /provider activation or persisted-profile path with a regression test.

A dedicatedCredentialsOnly route ignores OPENAI_API_KEY, so a profile
saved via /provider (which only sets OPENAI_API_KEY + OPENAI_BASE_URL)
relaunched unauthenticated with 'LLMTR auth is required'. Add LLMTR to the
dedicated-key profile surfaces — ProfileEnv type, secret/managed env-var
lists, SecretValueSource, buildLlmtrProfileEnv, the startup dispatch in
buildStartupProfileEnv, profileEnvMatchesProcessEnv, the
applyProviderProfileToProcessEnv mirror, and the persisted-profile
carry-over loop — so the key rides alongside OPENAI_API_KEY like Atlas,
NEAR, Fireworks, Venice, and MiMo.

Covered by regression tests for both the /provider activation path
(applyProviderProfileToProcessEnv) and persisted-profile relaunch
(buildLaunchEnv). Addresses PR review feedback from jatmn.
@knowhycodata

Copy link
Copy Markdown
Author

@jatmn thanks — fixed in 0189ca5.

LLMTR was added to all the dedicated-key profile surfaces so a key entered via /provider no longer relaunches unauthenticated:

  • ProfileEnv type, managed-env and SECRET_ENV_KEYS lists, and SecretValueSource
  • new buildLlmtrProfileEnv()
  • startup dispatch in buildStartupProfileEnv (route.gatewayId === 'llmtr')
  • profileEnvMatchesProcessEnv (llmtr.com host check)
  • the applyProviderProfileToProcessEnv mirror (LLMTR_API_KEY = profile.apiKey)
  • the persisted-profile dedicated-key carry-over loop

Regression tests cover both paths: the /provider activation mirror (applyProviderProfileToProcessEnv → asserts LLMTR_API_KEY) and persisted-profile relaunch (buildLaunchEnv, including live-key-over-persisted). typecheck, integrations:check, and knip are clean.

@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/utils/providerProfiles.test.ts`:
- Around line 614-627: The test sets process.env.LLMTR_API_KEY but this key is
not included in the RESTORED_KEYS list, causing environment state to leak into
subsequent tests. Add LLMTR_API_KEY to the RESTORED_KEYS array in the test setup
to ensure this environment variable is properly cleaned up after the test
execution, maintaining test isolation.

In `@src/utils/providerProfiles.ts`:
- Around line 1195-1206: The current code only handles the case where
route.gatewayId equals 'llmtr', but misses the scenario where a user has a
generic OpenAI provider profile with baseUrl pointing to llmtr.com. This causes
LLMTR_API_KEY to be lost on restart. After the existing route.gatewayId ===
'llmtr' check, add an additional condition to detect when an OpenAI profile's
baseUrl contains llmtr.com and apply the same buildLlmtrProfileEnv logic (with
getPrimaryModel, baseUrl, apiKey, and process.env) to preserve the LLMTR_API_KEY
in the environment, ensuring the profile is returned with the openai
configuration and supported custom headers applied.
🪄 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: b9580fdd-eb7f-4217-800f-d618f38b80f5

📥 Commits

Reviewing files that changed from the base of the PR and between a42bf5b and 0189ca5.

📒 Files selected for processing (4)
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx,js,jsx,py,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior in TypeScript and JavaScript files

Files:

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

⚙️ CodeRabbit configuration file

**: # Contributing to OpenClaude

Thanks for contributing.

OpenClaude is a fast-moving open-source coding-agent CLI with support for multiple providers, local backends, MCP, and a terminal-first workflow. The best contributions here are focused, well-tested, and easy to review.

Before You Start

  • Search existing issues and discussions before opening a new thread.
  • Check open pull requests for work that overlaps with your contribution. If a PR already exists that addresses the same change, open an issue or discussion first to align on direction — duplicate PRs may be closed without review.
  • Use issues for confirmed bugs and actionable feature work.
  • Use discussions for setup help, ideas, and general community conversation.
  • For larger changes, open an issue first so the scope is clear before implementation.
  • For security reports, follow SECURITY.md.

Pull Requests

Every PR needs a reason. Your PR description must include:

  • what changed and why
  • the user or developer impact
  • the exact checks you ran
  • a linked issue when one exists, using Fixes #123, `Closes `#123, or another clear link
  • screenshots when the PR touches UI, terminal presentation, or the VS Code extension
  • which provider path was tested when the PR changes provider behavior

The PR author is responsible for ensuring their PR is merge-ready. PRs with merge conflicts will not be reviewed or approved until the conflicts are resolved.

Issues are the recommended starting point for anything non-trivial — opening one first helps avoid wasted effort if the change is out of scope or already being worked on. Small fixes, doc corrections, and obvious improvements can stand on their own without a linked issue, as long as the PR description explains the intent.

What Gets Closed Without Review

PRs may be closed without review...

Files:

  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.ts
🔇 Additional comments (4)
src/utils/providerProfile.ts (1)

104-105: LGTM!

Also applies to: 134-135, 197-198, 225-227, 632-670, 1701-1708

src/utils/providerProfile.test.ts (1)

210-245: LGTM!

src/utils/providerProfiles.ts (1)

29-30: LGTM!

Also applies to: 581-584, 730-732

src/utils/providerProfiles.test.ts (1)

246-255: LGTM!

Comment thread src/utils/providerProfiles.test.ts
Comment thread src/utils/providerProfiles.ts
…solation

Address second-round review:
- buildOpenAICompatibleStartupEnv now mirrors LLMTR_API_KEY when a generic
  provider='openai' profile has OPENAI_BASE_URL pointed at llmtr.com (both
  the strict and fallback startup-env branches). Without this, a startup
  file carrying only OPENAI_API_KEY relaunched unauthenticated on the
  dedicatedCredentialsOnly LLMTR route.
- Add LLMTR_API_KEY to the test RESTORED_KEYS list so it no longer leaks
  into later tests.
- Cover the startup-file persistence path with a regression test
  (setActiveProviderProfile + persisted .openclaude-profile.json).
@knowhycodata

Copy link
Copy Markdown
Author

Both CodeRabbit findings addressed in ae10381:

  1. [Major] Startup persistence dropped LLMTR_API_KEY for generic openai profiles pointed at llmtr.com — buildOpenAICompatibleStartupEnv now mirrors LLMTR_API_KEY in both the strict and fallback startup-env branches when OPENAI_BASE_URL contains llmtr.com. Added a regression test that drives setActiveProviderProfile and asserts the persisted .openclaude-profile.json carries LLMTR_API_KEY.
  2. [Minor] Test isolation — added LLMTR_API_KEY to RESTORED_KEYS.

typecheck clean; provider profile suites 170 pass.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 15, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I found one issue that needs to be addressed before this is ready.

Findings

  • [P2] Add LLMTR to the shared secret redaction list
    src/utils/providerSecrets.ts:1
    This PR introduces LLMTR_API_KEY as a first-class credential and passes it into the profile sanitization paths, but the shared SECRET_ENV_KEYS list used by redactSecretValueForDisplay() and sanitizeProviderConfigValue() still does not include it. As a result, a plain LLMTR key that appears in a poisoned model/base-url field is treated as displayable config instead of being dropped/redacted, unlike the other known secret env values. Please add LLMTR_API_KEY to the shared secret collection and cover the redaction/sanitization behavior with a regression test so LLMTR keys cannot be shown or persisted through these helper paths.

Address review: LLMTR_API_KEY was a first-class credential but absent from
the shared SECRET_ENV_KEYS in providerSecrets.ts, so redactSecretValueForDisplay
and sanitizeProviderConfigValue treated a bare LLMTR key (no sk-/AIza prefix)
appearing in a poisoned model/base-url field as displayable config instead of
dropping/redacting it. Add LLMTR_API_KEY to the shared list and cover the
redaction + sanitization behavior with regression tests.
@knowhycodata

Copy link
Copy Markdown
Author

@jatmn fixed in 42011d5 — added LLMTR_API_KEY to the shared SECRET_ENV_KEYS in providerSecrets.ts, so redactSecretValueForDisplay() and sanitizeProviderConfigValue() now drop/redact a bare LLMTR key in poisoned model/base-url fields like the other known secrets. Added providerSecrets.test.ts covering both sanitization (poisoned field dropped, unrelated config kept) and redaction (key masked). typecheck clean; profile + secrets suites 173 pass.

@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/providerSecrets.test.ts`:
- Line 11: The llmtrKey constant uses a high-entropy API-key-like literal that
triggers security leak scanners in CI. Replace this secret-shaped test literal
with an obviously fake, low-entropy fixture string (such as a simple, clearly
non-real value like 'test-key' or 'fake-llmtr-key') that is unmistakably a test
value and will not be flagged by static analysis tools.
🪄 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: 813e78f7-09f5-44e8-9beb-6ad149447bce

📥 Commits

Reviewing files that changed from the base of the PR and between ae10381 and 42011d5.

📒 Files selected for processing (2)
  • src/utils/providerSecrets.test.ts
  • src/utils/providerSecrets.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise in code

Files:

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

⚙️ CodeRabbit configuration file

**: # Contributing to OpenClaude

Thanks for contributing.

OpenClaude is a fast-moving open-source coding-agent CLI with support for multiple providers, local backends, MCP, and a terminal-first workflow. The best contributions here are focused, well-tested, and easy to review.

Before You Start

  • Search existing issues and discussions before opening a new thread.
  • Check open pull requests for work that overlaps with your contribution. If a PR already exists that addresses the same change, open an issue or discussion first to align on direction — duplicate PRs may be closed without review.
  • Use issues for confirmed bugs and actionable feature work.
  • Use discussions for setup help, ideas, and general community conversation.
  • For larger changes, open an issue first so the scope is clear before implementation.
  • For security reports, follow SECURITY.md.

Pull Requests

Every PR needs a reason. Your PR description must include:

  • what changed and why
  • the user or developer impact
  • the exact checks you ran
  • a linked issue when one exists, using Fixes #123, `Closes `#123, or another clear link
  • screenshots when the PR touches UI, terminal presentation, or the VS Code extension
  • which provider path was tested when the PR changes provider behavior

The PR author is responsible for ensuring their PR is merge-ready. PRs with merge conflicts will not be reviewed or approved until the conflicts are resolved.

Issues are the recommended starting point for anything non-trivial — opening one first helps avoid wasted effort if the change is out of scope or already being worked on. Small fixes, doc corrections, and obvious improvements can stand on their own without a linked issue, as long as the PR description explains the intent.

What Gets Closed Without Review

PRs may be closed without review...

Files:

  • src/utils/providerSecrets.test.ts
  • src/utils/providerSecrets.ts
🪛 Betterleaks (1.5.0)
src/utils/providerSecrets.test.ts

[high] 11-11: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
src/utils/providerSecrets.ts (1)

10-10: LGTM!

Comment thread src/utils/providerSecrets.test.ts Outdated
Replace the high-entropy, API-key-shaped test literal with a clearly fake
low-entropy value so secret-leak scanners (Betterleaks) don't flag it in CI.
Behaviour is unchanged: the value still has no sk-/AIza prefix and is >8 chars,
so it exercises the same source-match redaction/sanitization path.
@knowhycodata

Copy link
Copy Markdown
Author

Fixed in 3072385 — replaced the API-key-shaped test fixture with an obviously-fake low-entropy value (fake-llmtr-test-key) so Betterleaks no longer flags it. Same code path is exercised (no sk-/AIza prefix, >8 chars). Tests still pass.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 16, 2026
jatmn
jatmn previously approved these changes Jun 16, 2026

@jatmn jatmn left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the updates. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.

@knowhycodata please fix, you are failing smoke

@jatmn jatmn added the new: provider/gateway Request to add a new provider or gateway label Jun 16, 2026
Adding the LLMTR gateway shifts every preset after Hicap one row down in the
/provider picker. navigateToPreset() steps by index against PRESET_ORDER, so
the stale list mis-navigated and the OpenAI/MiniMax/custom/Ollama/Atomic Chat
flows timed out. Insert 'LLMTR' between Hicap and LM Studio to match
ORDERED_PROVIDER_PRESETS.
@knowhycodata
knowhycodata dismissed stale reviews from jatmn and coderabbitai[bot] via ed8cbcf June 16, 2026 08:42
@knowhycodata

Copy link
Copy Markdown
Author

Fixed the CI failure (smoke-and-tests → ProviderManager.test.tsx) in ed8cbcf.

Root cause: adding the LLMTR gateway shifts every preset after Hicap one row down in the /provider picker. The test helper navigateToPreset() steps by index against a hardcoded PRESET_ORDER, so the stale list mis-navigated and the OpenAI / MiniMax / custom / Ollama / Atomic Chat flows timed out. Added 'LLMTR' between 'Hicap' and 'LM Studio' to match ORDERED_PROVIDER_PRESETS.

Verified locally: ProviderManager.test.tsx 24/24 pass; full bun test src shows no provider-related failures (remaining local failures are pre-existing Windows/env-specific and also fail on clean main).

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 16, 2026
jatmn
jatmn previously approved these changes Jun 16, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the updates. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.

@kevincodex1 LGTM

@knowhycodata

Copy link
Copy Markdown
Author

Rebased onto latest main (was CONFLICTING/DIRTY) — conflicts resolved in 7e5cf39. Branch is now MERGEABLE.

Conflicts were all in the secret-redaction area that main refactored in parallel (descriptor-derived getKnownProviderSecretEnvKeys()):

  • providerSecrets.ts: dropped my manual LLMTR_API_KEY fallback entry — it's now auto-derived from the LLMTR gateway's credentialEnvVars/validation.credentialEnvVars/preset apiKeyEnvVars, so no manual entry needed.
  • providerSecrets.test.ts (add/add): kept main's comprehensive descriptor-driven suite; added LLMTR_API_KEY to the representative-keys assertion.
  • providerProfile.ts: removed the obsolete local SECRET_ENV_KEYS array and closed SecretValueSource type in favor of main's open re-export from providerSecrets.ts. The LLMTR profile-env mirrors (buildLlmtrProfileEnv, startup/activation paths) are unchanged.

Local validation: typecheck clean, integrations:check up to date, and providerSecrets + providerProfile(s) + ProviderManager suites = 226 pass. (Re-review/CI approval needed since the merge commit reset the prior approvals.)

@knowhycodata

Copy link
Copy Markdown
Author

@jatmn @kevincodex1 — friendly nudge: this was approved by all of you (CodeRabbit + both human reviews) and CI was green, but merging main to clear the conflict reset the approvals, so it's back to REVIEW_REQUIRED / BLOCKED.

Nothing functional changed in the merge — it only resolved conflicts against main's parallel secret-redaction refactor:

  • dropped the now-redundant manual LLMTR_API_KEY fallback (it's auto-derived from the gateway descriptor)
  • kept your descriptor-driven providerSecrets.test.ts and added LLMTR_API_KEY to the representative-keys assertion
  • switched to the open SecretValueSource re-export; LLMTR profile-env mirrors unchanged

Local: typecheck clean, integrations:check up to date, 226 pass across providerSecrets + providerProfile(s) + ProviderManager.

Could a maintainer please approve the workflow run (fork PR shows action_required) and re-approve so this can land? Thanks for the thorough reviews 🙏

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 17, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the updates. I rechecked the changed paths and found one issue that still needs to be addressed.

Findings

  • [P2] Match LLMTR by hostname before mirroring the dedicated key
    src/utils/providerProfiles.ts:730
    The new LLMTR checks use baseUrl.toLowerCase().includes('llmtr.com') in the apply/startup/alignment paths, so any custom OpenAI-compatible host that merely contains that substring is treated as LLMTR-specific. For example, a saved generic profile pointed at https://not-llmtr.com/v1 mirrors and persists that provider's API key into LLMTR_API_KEY, even though the endpoint is not LLMTR. This reintroduces the same lookalike-host class the xAI path avoids with hostname parsing. Please add an isLlmtrBaseUrl() style helper that parses the URL host and only matches llmtr.com, then use it for the alignment, apply, and startup persistence checks with a regression test for a lookalike host.

The apply/startup/alignment paths used baseUrl.includes('llmtr.com'), so a
lookalike host like https://not-llmtr.com/v1 would mirror and persist its key
into LLMTR_API_KEY. Add isLlmtrBaseUrl() (URL hostname parse, exact llmtr.com
or *.llmtr.com) mirroring the isXaiBaseUrl/isFireworksBaseUrl pattern, and use
it in all four checks. Regression tests cover the helper (lookalike hosts) and
the apply path (not-llmtr.com does not mirror LLMTR_API_KEY). Addresses review
feedback from jatmn.
@knowhycodata

Copy link
Copy Markdown
Author

@jatmn fixed in 69ee0ca. Added isLlmtrBaseUrl() to routeMetadata.ts (URL hostname parse — matches llmtr.com / *.llmtr.com only), mirroring the isXaiBaseUrl/isFireworksBaseUrl pattern, and replaced all four substring checks (alignment, apply, and both startup-persistence branches). A lookalike host like https://not-llmtr.com/v1 no longer mirrors into LLMTR_API_KEY.

Regression tests: isLlmtrBaseUrl unit test (true for llmtr.com/api.llmtr.com; false for not-llmtr.com, llmtr.com.evil.example) and a behavioral test that a generic OpenAI profile on not-llmtr.com does not mirror the key. typecheck clean; 257 pass across the affected suites.

@knowhycodata

Copy link
Copy Markdown
Author

@jatmn @kevincodex1 — this should be ready for another look. The hostname finding is addressed in 69ee0ca:

  • new isLlmtrBaseUrl() (URL host parse, llmtr.com / *.llmtr.com only) replaces all four substring checks (alignment, apply, both startup-persistence branches)
  • lookalike hosts (not-llmtr.com, llmtr.com.evil.example) no longer mirror into LLMTR_API_KEY
  • regression tests added for the helper and the apply path

Branch is MERGEABLE (rebased on latest main); typecheck clean, 257 pass across the affected suites. Status is currently BLOCKED/CHANGES_REQUESTED only because the new commit needs a re-review and the fork PR's workflow run needs a maintainer to approve it (action_required).

Could a maintainer please approve the CI workflow and re-review? Thanks again for the careful passes 🙏

@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/routeMetadata.ts`:
- Around line 342-351: The `isLlmtrBaseUrl` function in routeMetadata.ts accepts
both exact `llmtr.com` and subdomain patterns like `*.llmtr.com`, but the LLMTR
gateway descriptor in `llmtr.ts` uses `matchBaseUrlHosts: ['llmtr.com']` with
only exact host matching. This creates inconsistent routing behavior where
subdomains pass the LLMTR validation but may not be routed correctly as LLMTR
hosts. Align these two contracts by either adding wildcard host pattern support
(e.g., `*.llmtr.com`) to the `matchBaseUrlHosts` array in the LLMTR descriptor
in `llmtr.ts`, or narrowing `isLlmtrBaseUrl` to perform only exact hostname
matching without accepting subdomains. Ensure both the function and the gateway
descriptor use the same host matching logic.

In `@src/utils/providerProfiles.test.ts`:
- Around line 630-647: Add a new regression test in the test file to cover the
LLMTR credential re-apply behavior referenced in the changed code path at lines
581-584 of src/utils/providerProfiles.ts. Create a test that uses the
applyActiveProviderProfileFromConfig function to verify that when LLMTR_API_KEY
is deleted from the environment after applying an LLMTR provider profile, the
key is properly restored on subsequent profile reapplication. This ensures the
dedicated-key relaunch behavior remains protected against future regressions.
🪄 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: 97db9132-e2af-4b89-b8d3-0ad95dc5847d

📥 Commits

Reviewing files that changed from the base of the PR and between 7e5cf39 and 69ee0ca.

📒 Files selected for processing (4)
  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (14)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

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

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/integrations/routeMetadata.test.ts
  • src/integrations/routeMetadata.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.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/integrations/routeMetadata.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.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
  • src/integrations/routeMetadata.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.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/integrations/routeMetadata.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.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/providerProfiles.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
  • src/integrations/routeMetadata.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
src/**/*provider*.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Provider implementations must follow documented patterns in docs/integrations/

Files:

  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
🔇 Additional comments (2)
src/integrations/routeMetadata.test.ts (1)

9-23: LGTM!

src/utils/providerProfiles.ts (1)

48-48: LGTM!

Also applies to: 581-584, 730-732, 990-992, 1039-1041

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

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the updates. I rechecked the changed paths and found two issues that still need to be addressed.

Findings

  • [P2] Align LLMTR subdomain routing with the new hostname helper
    src/integrations/gateways/llmtr.ts:38
    The latest patch makes isLlmtrBaseUrl() treat api.llmtr.com and other *.llmtr.com hosts as LLMTR, so the profile apply/startup paths now mirror LLMTR_API_KEY for those URLs. The descriptor validation/routing metadata only lists llmtr.com, though, and the shared resolver/validation paths use that list. As a result, OPENAI_BASE_URL=https://api.llmtr.com/v1 with LLMTR_API_KEY still resolves as a generic custom OpenAI endpoint and startup validation asks for OPENAI_API_KEY instead of accepting the LLMTR key. Please either add the matching wildcard host to the descriptor routing metadata and cover resolveRouteIdFromBaseUrl/validation for the subdomain case, or narrow the helper/test so the profile paths do not treat subdomains as LLMTR when the descriptor refuses to route them that way.

  • [P2] Complete CodeRabbit's request to cover LLMTR key drift re-apply
    src/utils/providerProfiles.test.ts:630
    CodeRabbit's current review asks for a regression test around the new isProcessEnvAlignedWithProfile() LLMTR branch, and that request is still valid. This PR now depends on LLMTR_API_KEY being part of the alignment check so an active LLMTR profile is re-applied when the generic OpenAI env survives but the dedicated key is missing, which is the same relaunch/drift class already covered for xAI and Fireworks. The implementation currently restores the key, but there is no LLMTR test exercising applyActiveProviderProfileFromConfig() after deleting LLMTR_API_KEY, so a future cleanup could silently drop the dedicated credential and make LLMTR relaunch unauthenticated again. Please complete that review request by adding the LLMTR drift regression alongside the existing xAI/Fireworks cases.

…ng + drift test

- Narrow isLlmtrBaseUrl() to exact 'llmtr.com', matching the descriptor's
  matchBaseUrlHosts: ['llmtr.com']. Previously it also accepted '*.llmtr.com',
  so api.llmtr.com would mirror LLMTR_API_KEY in the profile paths while route
  resolution/validation still classified it as a generic custom endpoint —
  split-brain behavior. Both contracts now agree on exact-host only.
- Add an LLMTR env-drift regression test: after deleting LLMTR_API_KEY,
  applyActiveProviderProfileFromConfig() re-applies the active LLMTR profile and
  restores the dedicated key, mirroring the xAI/Fireworks cases.

Addresses review feedback from jatmn and CodeRabbit.
@knowhycodata

Copy link
Copy Markdown
Author

@jatmn @coderabbitai both findings addressed in be167cc:

  1. Subdomain/descriptor mismatch — narrowed isLlmtrBaseUrl() to exact llmtr.com, matching the descriptor's matchBaseUrlHosts: ['llmtr.com']. Now the profile-mirror paths and route resolution/validation agree on exact-host only; api.llmtr.com is no longer treated as LLMTR by either side (no split-brain). Updated the unit test to assert the subdomain is rejected.
  2. LLMTR drift regression — added re-applies LLMTR active profile when LLMTR_API_KEY is missing (env drift), mirroring the xAI/Fireworks cases: after deleting LLMTR_API_KEY, applyActiveProviderProfileFromConfig() re-applies and restores the dedicated key.

typecheck clean; 258 pass across the affected suites (providerProfile(s), providerSecrets, routeMetadata, ProviderManager). CI was green on the prior commit.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

CodeRabbit chat interactions are restricted to organization members for this repository. Ask an organization member to interact with CodeRabbit, or set chat.allow_non_org_members: true in your configuration.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 17, 2026
jatmn
jatmn previously approved these changes Jun 17, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the updates. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.

@kevincodex1 LGTM

@kevincodex1

Copy link
Copy Markdown
Member

please rebase and fix conflict again . theres new conflict

@knowhycodata
knowhycodata dismissed stale reviews from jatmn and coderabbitai[bot] via b59862f June 18, 2026 04:27
@knowhycodata

Copy link
Copy Markdown
Author

Re-synced with main (it had advanced and gone CONFLICTING again) in b59862f — branch is MERGEABLE again.

The only conflict was the generated integrationArtifacts.generated.ts vs main's new github-enterprise gateway; I resolved it by re-running bun run integrations:generate so both descriptors coexist. No functional change to the LLMTR work.

Validated the full merge locally (CI-equivalent): typecheck clean, integrations:check up to date, build OK, and bun test src = 4273 pass (the only failures are pre-existing POSIX-path tests that also fail on a clean main checkout on Windows and pass on the Linux CI runners).

@jatmn @kevincodex1 — you'd both already approved; the conflict-resolution merge dismissed the approvals. Could a maintainer please approve the workflow run + re-approve and merge before main drifts again? Happy to keep re-syncing but each merge resets approvals, so a prompt merge would let it land. Thanks! 🙏

@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/utils/providerProfile.ts (1)

1275-1315: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve github-enterprise when honoring CLAUDE_CODE_USE_GITHUB.

Line 1276 currently forces GitHub flag overrides to 'github'. If the selected/persisted profile is 'github-enterprise', this downgrade drops enterprise env shaping and can strip GITHUB_COPILOT_KEY / GITHUB_ENTERPRISE_URL on relaunch.

Suggested fix
   for (const [envKey, provider] of explicitProfileOverrides) {
     if (isEnvTruthy(processEnv[envKey])) {
+      const overriddenProfile: ProviderProfile =
+        envKey === 'CLAUDE_CODE_USE_GITHUB' &&
+        selectedProfile === 'github-enterprise'
+          ? 'github-enterprise'
+          : provider
       const isCodexOAuthProfile =
         selectedProfile === 'codex' &&
-        provider === 'openai' &&
+        overriddenProfile === 'openai' &&
         persistedEnv.CODEX_CREDENTIAL_SOURCE === 'oauth'
       if (!isCodexOAuthProfile) {
-        selectedProfile = provider
+        selectedProfile = overriddenProfile
       }
       break
     }
   }
🤖 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/utils/providerProfile.ts` around lines 1275 - 1315, The issue is in the
explicit profile override loop where selectedProfile is unconditionally set to
the provider value (e.g., 'github') when the corresponding environment variable
is true. This causes 'github-enterprise' to be downgraded to 'github', skipping
the enterprise-specific environment setup code that applies
GITHUB_ENTERPRISE_URL and GITHUB_COPILOT_KEY. To fix this, when the provider is
'github' and the current selectedProfile is already 'github-enterprise',
preserve the enterprise profile instead of downgrading it. Only override to
'github' if the selected profile is not already a GitHub enterprise variant.
🤖 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/utils/providerProfile.ts`:
- Around line 1275-1315: The issue is in the explicit profile override loop
where selectedProfile is unconditionally set to the provider value (e.g.,
'github') when the corresponding environment variable is true. This causes
'github-enterprise' to be downgraded to 'github', skipping the
enterprise-specific environment setup code that applies GITHUB_ENTERPRISE_URL
and GITHUB_COPILOT_KEY. To fix this, when the provider is 'github' and the
current selectedProfile is already 'github-enterprise', preserve the enterprise
profile instead of downgrading it. Only override to 'github' if the selected
profile is not already a GitHub enterprise variant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6253a6a2-0758-4831-81c4-9798901af4de

📥 Commits

Reviewing files that changed from the base of the PR and between be167cc and b59862f.

⛔ Files ignored due to path filters (1)
  • src/integrations/generated/integrationArtifacts.generated.ts is excluded by !**/generated/**, !src/integrations/generated/**
📒 Files selected for processing (7)
  • .env.example
  • README.md
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfile.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerSecrets.test.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/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.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/providerSecrets.test.ts
  • README.md
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • src/utils/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.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/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • src/utils/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/utils/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • src/utils/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.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/providerSecrets.test.ts
  • README.md
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.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/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.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/providerSecrets.test.ts
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.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/providerSecrets.test.ts
  • README.md
  • src/utils/providerProfile.test.ts
  • src/utils/providerProfiles.test.ts
  • src/utils/providerProfiles.ts
  • src/utils/providerProfile.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:

  • README.md
🔇 Additional comments (7)
src/utils/providerProfile.ts (1)

75-76: LGTM!

Also applies to: 118-118, 133-133, 154-155, 308-308, 335-347, 934-935, 1210-1213, 1323-1323, 1353-1353, 1375-1375, 1397-1397, 1434-1434, 1478-1478, 1536-1536, 1558-1558, 1576-1576, 1595-1595, 1777-1787

src/utils/providerProfile.test.ts (1)

175-207: LGTM!

Also applies to: 436-455

src/utils/providerProfiles.ts (1)

84-97: LGTM!

Also applies to: 104-106, 132-167, 444-445, 470-471, 545-563, 719-727, 1178-1197

src/utils/providerProfiles.test.ts (1)

36-37: LGTM!

Also applies to: 358-492, 1236-1265

.env.example (1)

4-15: LGTM!

Also applies to: 147-148, 516-527

README.md (1)

108-109: LGTM!

Also applies to: 127-129

src/utils/providerSecrets.test.ts (1)

138-138: LGTM!

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the updates. I rechecked the current changed paths and found one issue that still needs to be addressed.

Findings

  • [P2] Complete CodeRabbit's request to preserve GitHub Enterprise launch env
    src/utils/providerProfile.ts:1276
    CodeRabbit's current review item points out that the explicit CLAUDE_CODE_USE_GITHUB override collapses a selected github-enterprise profile to plain github, and that request is still valid. When buildLaunchEnv() is called for a persisted Enterprise profile while CLAUDE_CODE_USE_GITHUB=1 is already present, the loop assigns selectedProfile = 'github', so the Enterprise-only branch never runs and the returned env drops both GITHUB_ENTERPRISE_URL and GITHUB_COPILOT_KEY. That means an Enterprise Copilot profile can relaunch as a public GitHub-shaped profile without the Enterprise URL/credential. Please complete that review request by preserving github-enterprise when honoring the shared GitHub flag.

@jatmn

jatmn commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

closing as abandoned

@knowhycodata

Copy link
Copy Markdown
Author

Reopened this as #2135 — GitHub refuses to reopen this PR (the reopen call fails validation and the head here stays pinned to the old commit), so the work is on a branch rebuilt on current main instead.

Same branch, brought up to date with main and with the model catalog corrected. Continuing there; no need to action anything here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new: provider/gateway Request to add a new provider or gateway

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants