Skip to content

feat(providers): add OrcaRouter as a named OpenAI-compatible provider - #436

Open
lovejones2914-spec wants to merge 1 commit into
steipete:mainfrom
lovejones2914-spec:add-orcarouter-provider
Open

feat(providers): add OrcaRouter as a named OpenAI-compatible provider#436
lovejones2914-spec wants to merge 1 commit into
steipete:mainfrom
lovejones2914-spec:add-orcarouter-provider

Conversation

@lovejones2914-spec

@lovejones2914-spec lovejones2914-spec commented Aug 29, 2026

Copy link
Copy Markdown

What

Adds OrcaRouter as a named provider, mirroring the existing OpenRouter wiring as closely as possible. OrcaRouter is an OpenAI-compatible AI gateway built for both models and agents. Like OpenRouter, it exposes a provider/model namespace across many models, but it also combines adaptive routing, automatic failover, zero-markup inference, observability, guardrails, and agent-tool governance behind the same endpoint. Adding orcarouter as a first-class provider means Oracle's users can use that stack directly, without treating OrcaRouter as an anonymous custom base URL. It also runs gateway-level, zero-trust security for AI agents on the same endpoint, screening every prompt/response and governing every tool call on a default-deny basis, with no application code changes.

Changes

This mirrors how Oracle already wires OpenRouter (the shared provider-routing contract in providerRoutePlan.ts), file by file:

  • src/oracle/modelResolver.ts: detect/normalize api.orcarouter.ai base URLs (isOrcaRouterBaseUrl / defaultOrcaRouterBaseUrl / normalizeOrcaRouterBaseUrl), and hydrate model metadata from the OrcaRouter /v1/models catalog plus pricing ratios from the public /api/pricing endpoint. The catalog returns the same OpenRouter-shaped data[] payload, so the existing mapToOpenRouterId mapping is reused. The hostname check is boundary-safe (only api.orcarouter.ai or a subdomain matches), so a lookalike hostname never receives OrcaRouter credentials.
  • src/oracle/client.ts: route OrcaRouter base URLs through the OpenAI chat/completions adapter (same as OpenRouter/custom proxies) and forward optional attribution headers HTTP-Referer / X-Title from ORCAROUTER_REFERER / ORCAROUTER_TITLE.
  • src/oracle/providerRoutePlan.ts: route orcarouter/... model ids to https://api.orcarouter.ai/v1 and select ORCAROUTER_API_KEY as the key source. Unprefixed custom model ids keep the existing OpenRouter fallback, so current setups are unchanged.
  • src/oracle/run.ts, src/cli/sessionRunner.ts, src/cli/engine.ts: thread the OrcaRouter route, missing-key message, and API-mode detection through the runtime.
  • src/oracle/providerFailures.ts: classify OrcaRouter auth failures and redact sk-orca-... keys from error messages.
  • docs/orcarouter.md: new provider guide (setup, models, headers), plus OrcaRouter rows in the README, docs/index.md, docs/install.md, docs/openai-endpoints.md, docs/cli-reference.md, docs/mythical-pro-agents.md, and docs/followup.md provider tables.
  • tests/: unit coverage for catalog hydration, orcarouter/... routing, key-source selection, failure hints, and lookalike-hostname rejection.

How it was verified

  • pnpm typecheck, pnpm lint, and pnpm format:check all pass.
  • Full test suite passes (1919 tests; the only failure is a pre-existing browserTabs test that needs rsync, which is not installed in this container).
  • L3 live test against the real OrcaRouter API: resolveProviderRoute selects the OrcaRouter route (providerLabel=OrcaRouter, base=api.orcarouter.ai/v1, keySource=ORCAROUTER_API_KEY), and a real chat/completions call through createDefaultClientFactory returned "ORCA-LIVE-OK".
route: providerLabel=OrcaRouter base=api.orcarouter.ai/v1 ok=true keySource=ORCAROUTER_API_KEY
response: "ORCA-LIVE-OK"

OrcaRouter API keys start with sk-orca-; full model catalog is at https://www.orcarouter.ai/models. Questions or feedback: Discord: discord.gg/YEubt8enRA · X: https://x.com/OrcaRouter

I'm an engineer on the OrcaRouter team.

Mirror the existing OpenRouter wiring end to end so OrcaRouter works as a
first-class provider rather than an anonymous custom base URL:

- modelResolver: detect/normalize api.orcarouter.ai base URLs, add a default
  base, and hydrate model metadata + pricing from the OrcaRouter /v1/models
  catalog and /api/pricing ratios.
- client: route OrcaRouter base URLs through the OpenAI chat/completions
  adapter and forward HTTP-Referer / X-Title attribution headers from
  ORCAROUTER_REFERER / ORCAROUTER_TITLE.
- providerRoutePlan/run/sessionRunner/engine: add an orcarouter/ model-id
  route and ORCAROUTER_API_KEY key source, with a boundary-safe hostname
  classifier (lookalike domains never receive OrcaRouter credentials).
- providerFailures: classify OrcaRouter auth failures and redact sk-orca- keys.
- docs: docs/orcarouter.md plus OrcaRouter rows in the provider tables.
- tests: unit coverage for catalog hydration, routing, failure hints, and
  lookalike-host rejection; L3 live call verified against api.orcarouter.ai.
@clawsweeper

clawsweeper Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Aug 29, 2026
@clawsweeper

clawsweeper Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed August 29, 2026, 12:01 AM ET / 04:01 UTC.

ClawSweeper review

What this changes

The PR adds OrcaRouter as a named OpenAI-compatible API provider, including routing, credential selection, catalog metadata, diagnostics, tests, and documentation.

Merge readiness

⚠️ Needs maintainer review before merge - 11 items remain

Keep this PR open for maintainer product direction and revision: the named-provider idea is coherent and has a real API trace, but the new credential route permits an HTTP downgrade, the advertised ORCAROUTER_API_KEY-only path fails for the default model, and catalog resolution is not actually best-effort when pricing fetches fail.

Priority: P1
Reviewed head: 8bb9a781c5026e87e326aca98caceafadbc77caa
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) A real provider response supports the intended path, but concrete credential, fallback, and resilience defects block a higher rating.
Proof confidence 🐚 platinum hermit (4/6) Sufficient (terminal): The PR body supplies terminal output from a real OrcaRouter HTTPS path: the changed route resolver selected OrcaRouter and the changed default client completed a chat-completions call with ORCA-LIVE-OK. That is sufficient proof of the allowed production path, while the review findings identify unexercised failure and security cases.
Patch quality 🦐 gold shrimp (3/6) Security review found an item that needs attention.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): The PR body supplies terminal output from a real OrcaRouter HTTPS path: the changed route resolver selected OrcaRouter and the changed default client completed a chat-completions call with ORCA-LIVE-OK. That is sufficient proof of the allowed production path, while the review findings identify unexercised failure and security cases.
Evidence reviewed 6 items HTTP credential downgrade: The introduced OrcaRouter host predicate accepts any URL scheme; the route planner then selects ORCAROUTER_API_KEY for that predicate, and the client passes the supplied base URL to the OpenAI-compatible client. Oracle’s existing endpoint documentation explicitly supports HTTP custom endpoints, so an http://api.orcarouter.ai base URL can send the named credential without TLS.
Default ORCAROUTER_API_KEY route is incomplete: The new engine detection enters API mode when only ORCAROUTER_API_KEY is set, but the OrcaRouter fallback is limited to model IDs beginning with orcarouter/. The default GPT model consequently still selects OPENAI_API_KEY, contrary to the new provider documentation’s fallback claim.
Pricing fallback is not isolated: The model and pricing requests are combined with Promise.all; a rejected pricing request rejects the whole helper and causes model-catalog metadata to be discarded, despite the surrounding comment and documentation describing pricing as best-effort.
Findings 4 actionable findings [P1] Require HTTPS before selecting OrcaRouter credentials
[P1] Route the ORCAROUTER_API_KEY-only default invocation
[P2] Make the pricing request genuinely best-effort
Security Needs attention OrcaRouter credentials can be routed over HTTP: The new hostname-only predicate classifies an HTTP OrcaRouter URL as trusted; downstream routing selects ORCAROUTER_API_KEY and the OpenAI-compatible client receives that base URL, permitting plaintext credential transmission.

How this fits together

Oracle’s API-mode CLI resolves a requested model to a provider route and credential, then constructs the corresponding client for the provider endpoint. This change adds an OrcaRouter route that feeds the existing OpenAI-compatible chat-completions adapter.

flowchart LR
  A[CLI model request] --> B[Engine selection]
  B --> C[Provider route selection]
  C --> D[Credential selection]
  D --> E[OrcaRouter endpoint]
  E --> F[OpenAI-compatible client]
  F --> G[Model response and session logs]
Loading

Decision needed

Question Recommendation
Should Oracle maintain a named OrcaRouter integration, rather than direct users to the existing OpenAI-compatible custom base URL and model override path? Sponsor a narrow named integration: Accept the provider surface after the security and routing fixes, with tests constrained to the documented HTTPS API and graceful catalog degradation.

Why: This adds a maintained third-party endpoint, credential convention, catalog format, and pricing-ratio dependency; source review cannot determine whether that recurring product surface is wanted.

Before merge

  • Require HTTPS before selecting OrcaRouter credentials (P1) - isOrcaRouterBaseUrl accepts http://api.orcarouter.ai, and that predicate makes the route planner select ORCAROUTER_API_KEY before the client dispatches to that URL. Oracle supports HTTP custom endpoints, so this can transmit the new named credential in plaintext; require https: here and add a rejection test.
  • Route the ORCAROUTER_API_KEY-only default invocation (P1) - The new engine check starts API mode when only ORCAROUTER_API_KEY is configured, but this fallback remains false unless the model starts with orcarouter/. The default model then errors for OPENAI_API_KEY, contradicting the documented claim that OrcaRouter is selected when no provider-specific key is available. Add the intended fallback precedence and exercise a real runOracle path.
  • Make the pricing request genuinely best-effort (P2) - A network rejection from /api/pricing rejects Promise.all, so the outer catch drops a successful /v1/models result and uses synthesized metadata instead. Fetch or await pricing independently so a pricing outage cannot remove model IDs and context limits.
  • Add the user-facing feature to Unreleased notes (P3) - This adds a provider users can select directly, but the PR leaves CHANGELOG.md unchanged despite the applicable repository feature-release-note guidance. Add one concise Unreleased entry.
  • Resolve security concern: OrcaRouter credentials can be routed over HTTP - The new hostname-only predicate classifies an HTTP OrcaRouter URL as trusted; downstream routing selects ORCAROUTER_API_KEY and the OpenAI-compatible client receives that base URL, permitting plaintext credential transmission.
  • Resolve merge risk (P1) - The new named-provider classifier trusts HTTP URLs and can transmit ORCAROUTER_API_KEY without TLS.
  • Resolve merge risk (P1) - With only ORCAROUTER_API_KEY set, automatic API selection leads the default model to fail for OPENAI_API_KEY rather than use OrcaRouter.
  • Resolve merge risk (P1) - A transient failure of the unauthenticated pricing endpoint discards a successful model catalog response.
  • Resolve merge risk (P1) - Maintainers have not yet accepted the ongoing provider-specific endpoint and pricing-contract surface over the existing generic custom-base-URL path.
  • Complete next step (P2) - A maintainer must first decide whether Oracle should own a provider-specific OrcaRouter contract; after sponsorship, the listed code and changelog corrections are concrete contributor follow-up.

Findings

  • [P1] Require HTTPS before selecting OrcaRouter credentials — src/oracle/modelResolver.ts:66-71
  • [P1] Route the ORCAROUTER_API_KEY-only default invocation — src/oracle/providerRoutePlan.ts:206-210
  • [P2] Make the pricing request genuinely best-effort — src/oracle/modelResolver.ts:213-221
  • [high] OrcaRouter credentials can be routed over HTTP — src/oracle/modelResolver.ts:71
Agent review details

Security

Needs attention: The new named-provider credential route does not require HTTPS before dispatch.

Review metrics

Metric Value Why it matters
Change surface 19 files; +513, -30 The feature spans routing, client creation, diagnostics, tests, and user documentation.
Production versus tests production +278/-16, tests +166/-0 The substantial routing expansion has focused unit coverage, but the missing edge cases affect the provider’s actual credential and fallback path.

Merge-risk options

Maintainer options:

  1. Repair the named-provider boundary (recommended)
    Require HTTPS before selecting ORCAROUTER_API_KEY, make the documented key-only path routable, and preserve successful model discovery when pricing is unavailable.
  2. Keep only generic gateway configuration
    Pause or close the named integration if maintainers do not want to own OrcaRouter-specific credentials, catalog parsing, and pricing semantics.

Technical review

Best possible solution:

If maintainers sponsor named OrcaRouter support, restrict its credential route to HTTPS, make the ORCAROUTER_API_KEY-only fallback match the documented invocation, isolate optional pricing failures from model discovery, add regression coverage, and add one Unreleased changelog entry.

Do we have a high-confidence way to reproduce the issue?

Yes, source inspection gives two deterministic paths: configure only ORCAROUTER_API_KEY and use the default model to reach a missing OPENAI_API_KEY error, or use an HTTP OrcaRouter base URL to select the named credential without a TLS guard. No target code was executed in this read-only review.

Is this the best way to solve the issue?

No. The existing custom base URL and model-override path already supports OpenAI-compatible gateways, so a named integration needs explicit sponsorship; if sponsored, it must fix the TLS, default-routing, and optional-pricing faults before merge.

Full review comments:

  • [P1] Require HTTPS before selecting OrcaRouter credentials — src/oracle/modelResolver.ts:66-71
    isOrcaRouterBaseUrl accepts http://api.orcarouter.ai, and that predicate makes the route planner select ORCAROUTER_API_KEY before the client dispatches to that URL. Oracle supports HTTP custom endpoints, so this can transmit the new named credential in plaintext; require https: here and add a rejection test.
    Confidence: 0.98
  • [P1] Route the ORCAROUTER_API_KEY-only default invocation — src/oracle/providerRoutePlan.ts:206-210
    The new engine check starts API mode when only ORCAROUTER_API_KEY is configured, but this fallback remains false unless the model starts with orcarouter/. The default model then errors for OPENAI_API_KEY, contradicting the documented claim that OrcaRouter is selected when no provider-specific key is available. Add the intended fallback precedence and exercise a real runOracle path.
    Confidence: 0.97
  • [P2] Make the pricing request genuinely best-effort — src/oracle/modelResolver.ts:213-221
    A network rejection from /api/pricing rejects Promise.all, so the outer catch drops a successful /v1/models result and uses synthesized metadata instead. Fetch or await pricing independently so a pricing outage cannot remove model IDs and context limits.
    Confidence: 0.96
  • [P3] Add the user-facing feature to Unreleased notes — docs/orcarouter.md:1-3
    This adds a provider users can select directly, but the PR leaves CHANGELOG.md unchanged despite the applicable repository feature-release-note guidance. Add one concise Unreleased entry.
    Confidence: 0.93

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against bbc1b3b0261d.

Labels

Label changes:

  • add P1: The PR introduces a reachable named-provider credential exposure and a documented setup path that fails at runtime.
  • add merge-risk: 🚨 auth-provider: ORCAROUTER_API_KEY changes automatic API selection but does not establish a working default provider route.
  • add merge-risk: 🚨 security-boundary: The new OrcaRouter credential selection treats an HTTP URL as trusted and can send the key without TLS.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body supplies terminal output from a real OrcaRouter HTTPS path: the changed route resolver selected OrcaRouter and the changed default client completed a chat-completions call with ORCA-LIVE-OK. That is sufficient proof of the allowed production path, while the review findings identify unexercised failure and security cases.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body supplies terminal output from a real OrcaRouter HTTPS path: the changed route resolver selected OrcaRouter and the changed default client completed a chat-completions call with ORCA-LIVE-OK. That is sufficient proof of the allowed production path, while the review findings identify unexercised failure and security cases.

Label justifications:

  • P1: The PR introduces a reachable named-provider credential exposure and a documented setup path that fails at runtime.
  • merge-risk: 🚨 security-boundary: The new OrcaRouter credential selection treats an HTTP URL as trusted and can send the key without TLS.
  • merge-risk: 🚨 auth-provider: ORCAROUTER_API_KEY changes automatic API selection but does not establish a working default provider route.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body supplies terminal output from a real OrcaRouter HTTPS path: the changed route resolver selected OrcaRouter and the changed default client completed a chat-completions call with ORCA-LIVE-OK. That is sufficient proof of the allowed production path, while the review findings identify unexercised failure and security cases.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body supplies terminal output from a real OrcaRouter HTTPS path: the changed route resolver selected OrcaRouter and the changed default client completed a chat-completions call with ORCA-LIVE-OK. That is sufficient proof of the allowed production path, while the review findings identify unexercised failure and security cases.

Evidence

Security concerns:

  • [high] OrcaRouter credentials can be routed over HTTP — src/oracle/modelResolver.ts:71
    The new hostname-only predicate classifies an HTTP OrcaRouter URL as trusted; downstream routing selects ORCAROUTER_API_KEY and the OpenAI-compatible client receives that base URL, permitting plaintext credential transmission.
    Confidence: 0.98

What I checked:

  • HTTP credential downgrade: The introduced OrcaRouter host predicate accepts any URL scheme; the route planner then selects ORCAROUTER_API_KEY for that predicate, and the client passes the supplied base URL to the OpenAI-compatible client. Oracle’s existing endpoint documentation explicitly supports HTTP custom endpoints, so an http://api.orcarouter.ai base URL can send the named credential without TLS. (src/oracle/modelResolver.ts:71, 8bb9a781c502)
  • Default ORCAROUTER_API_KEY route is incomplete: The new engine detection enters API mode when only ORCAROUTER_API_KEY is set, but the OrcaRouter fallback is limited to model IDs beginning with orcarouter/. The default GPT model consequently still selects OPENAI_API_KEY, contrary to the new provider documentation’s fallback claim. (src/oracle/providerRoutePlan.ts:210, 8bb9a781c502)
  • Pricing fallback is not isolated: The model and pricing requests are combined with Promise.all; a rejected pricing request rejects the whole helper and causes model-catalog metadata to be discarded, despite the surrounding comment and documentation describing pricing as best-effort. (src/oracle/modelResolver.ts:213, 8bb9a781c502)
  • Real nominal-path proof: The supplied PR body records a real OrcaRouter route selection and chat-completions response of ORCA-LIVE-OK through the changed production factory. It proves the allowed HTTPS path, but not the unsafe HTTP, default-key, or pricing-failure cases. (8bb9a781c502)
  • Repository release-note policy: The target policy calls for a changelog update when a completed feature matters to end users; this user-facing provider addition leaves CHANGELOG.md unchanged. (AGENTS.md:35, 8bb9a781c502)
  • Feature-history routing: The shared provider-route resolution on current lineage appears to date to Peter Steinberger’s refactor, making him the closest current code-history contact for the added route. (src/oracle/providerRoutePlan.ts:72, 201664683045)

Likely related people:

  • Peter Steinberger: Introduced the current shared provider-route resolution that this PR extends. (role: shared provider-routing introducer; confidence: medium; commits: 201664683045, 9dc102ddc5d6; files: src/oracle/providerRoutePlan.ts, src/oracle/modelResolver.ts)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Require HTTPS in the OrcaRouter classifier and add the HTTP rejection regression.
  • Add a run-level regression for an ORCAROUTER_API_KEY-only default invocation and a catalog test where pricing rejects after models succeed.
  • Add the concise Unreleased entry required for this user-facing provider feature.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

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

Labels

merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant