Skip to content

feat: add OrcaRouter as a first-class provider - #260

Open
nissrin2020ali-ux wants to merge 1 commit into
teamchong:mainfrom
nissrin2020ali-ux:feat/orcarouter-provider
Open

feat: add OrcaRouter as a first-class provider#260
nissrin2020ali-ux wants to merge 1 commit into
teamchong:mainfrom
nissrin2020ali-ux:feat/orcarouter-provider

Conversation

@nissrin2020ali-ux

Copy link
Copy Markdown

What breaks without this

pxpipe's token-saving proxy already ships a named-provider slot (PXPIPE_PROVIDER=cloudflare-ai-gateway) for routing both API families through one OpenAI-compatible gateway, but there is no first-class entry for OrcaRouter. 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. Users who point pxpipe at OrcaRouter today have to treat it as an anonymous custom base URL; this PR makes it a named provider so the whole stack is reachable without hand-rolled OPENAI_UPSTREAM/ANTHROPIC_UPSTREAM overrides.

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.

The change

PXPIPE_PROVIDER=orcarouter routes both API families to OrcaRouter's single https://api.orcarouter.ai namespace, fully parallel to how cloudflare-ai-gateway is wired today. OrcaRouter speaks Anthropic Messages, OpenAI Responses, and OpenAI Chat Completions under one /v1 root (unlike Cloudflare's split /anthropic + /openai gateway shape), so the only real difference from the Cloudflare branch is that /v1 is kept rather than stripped.

File-by-file correspondence:

file what changed
src/core/proxy.ts ProxyConfig.provider union gains 'orcarouter'; resolveUpstreams() gains the OrcaRouter branch (both families → same base, stripOpenAIV1: false); passthroughUpstream falls back to the new DEFAULT_ORCAROUTER_UPSTREAM (https://api.orcarouter.ai) when no PXPIPE_GATEWAY_BASE_URL is set.
src/node.ts RuntimeConfig.provider and parseProvider() accept 'orcarouter'; help text documents it, noting PXPIPE_GATEWAY_BASE_URL is now optional (OrcaRouter has a default base).
tests/gateway.test.ts Mirrors the existing Cloudflare resolveUpstreams + end-to-end routing tests for orcarouter (default base, base override, /v1 kept on Anthropic Messages / OpenAI Responses / Chat Completions).
docs/CLAUDE_CODE_PROVIDER_ROUTING.md New "OrcaRouter" subsection beside the Cloudflare/Novita examples, with the env-var setup and Claude Code usage.

Verify

pnpm run typecheck   # passes
pnpm run audit       # No known vulnerabilities found
pnpm exec vitest run tests/gateway.test.ts  # 18 passed (5 new orcarouter tests)

# L3 live test — real request through the proxy to api.orcarouter.ai:
#   PXPIPE_PROVIDER=orcarouter ANTHROPIC_API_KEY=… node bin/cli.js
#   POST /v1/messages      → 200 (model: claude-fable-5)
#   POST /v1/chat/completions → 200
#   proxy log: anthropic upstream → https://api.orcarouter.ai
#              openai upstream    → https://api.orcarouter.ai
  • Rebased on current main
  • pnpm test and pnpm typecheck pass (the one local failure — restart.test.ts, "reads the real process table" — is an environment artifact: this container has no ps, so listProcesses() returns []; it passes on CI's ubuntu-24.04)
  • No raw prompts, credentials, session files, or machine identifiers

I'm an engineer on the OrcaRouter team. Discord: discord.gg/YEubt8enRA · X: https://x.com/OrcaRouter

Mirror the existing cloudflare-ai-gateway named-provider slot so both
API families route through OrcaRouter's single OpenAI/Anthropic-
compatible /v1 namespace. PXPIPE_PROVIDER=orcarouter resolves both
upstreams to https://api.orcarouter.ai (overridable with
PXPIPE_GATEWAY_BASE_URL), keeping /v1 path segments.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant