Skip to content

feat(providers): add OrcaRouter as a named provider - #6978

Open
XiaoHuo888-hue wants to merge 1 commit into
simstudioai:stagingfrom
XiaoHuo888-hue:add-orcarouter-provider
Open

feat(providers): add OrcaRouter as a named provider#6978
XiaoHuo888-hue wants to merge 1 commit into
simstudioai:stagingfrom
XiaoHuo888-hue:add-orcarouter-provider

Conversation

@XiaoHuo888-hue

Copy link
Copy Markdown

Summary

Add OrcaRouter as a first-class named provider in Sim's model picker, mirroring the existing OpenRouter integration. OrcaRouter is an OpenAI-compatible gateway (https://api.orcarouter.ai/v1, key prefix sk-orca-) that routes across many upstream providers — the same shape as OpenRouter, so it fits the existing reseller-provider wiring with no new architectural surface.

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.

What changed

  • New orcarouter provider (apps/sim/providers/orcarouter/): OpenAI-compatible chat completions with the full tool loop and streaming, using the same shared streaming/tool helpers as the other OpenAI-compatible providers. Targets https://api.orcarouter.ai/v1 via the OpenAI SDK.
  • Model catalog route (apps/sim/app/api/providers/orcarouter/models/route.ts): enumerates the public OrcaRouter /v1/models catalog (like OpenRouter's, no key required to list), filtering to chat-capable models.
  • Full registration across the provider registry, ProviderId/ProviderName/BYOKProviderId unions, PROVIDER_DEFINITIONS + DYNAMIC_MODEL_PROVIDERS, provider metadata, attachment support (images + PDFs), the providers store, the model-list loader, and the query/contract wiring.
  • BYOK key resolution for orcarouter keys, with workspace/org key support.
  • Docs: Agent block provider list now mentions OrcaRouter.

Models are typed as orcarouter/<id> and appear in the model combobox automatically via the catalog route.

Testing

  • vitest — all provider, blocks, stores, contracts, and api-provider tests pass: 2807 tests across 194 files (including a new 10-test orcarouterProvider suite).
  • tsc --noEmit — clean.
  • biome check — clean on all changed files.
  • check:api-validation — passes (baseline route count bumped 1162 → 1163 for the new route).
  • L3 live verification against the OrcaRouter API:
    • GET https://api.orcarouter.ai/v1/models200
    • POST https://api.orcarouter.ai/v1/chat/completions with model: "orcarouter/auto"200, returned ORCA-LIVE-OK (routed to gemini-3.1-flash-lite).

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Disclosure: I'm an engineer on the OrcaRouter team.

Add OrcaRouter (https://api.orcarouter.ai/v1) as a first-class named
provider alongside OpenRouter, mirroring the existing OpenAI-compatible
gateway wiring.

- providers/orcarouter: chat completions + tool loop + streaming, targeting
  https://api.orcarouter.ai/v1 with the OpenAI SDK
- app/api/providers/orcarouter/models: enumerates the public OrcaRouter
  model catalog (https://api.orcarouter.ai/v1/models)
- registry/types/models/utils/attachments/stores/hooks/loader: register
  the orcarouter provider id across all model pickers, BYOK key resolution,
  attachment support, and the model-list sync
- docs: mention OrcaRouter in the Agent block provider list

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: XiaoHuo888-hue <jinhao.song@myflashcloud.com>
@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

@cursor

cursor Bot commented Aug 22, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New outbound LLM provider and BYOK key path for inference; additive and patterned on OpenRouter, but it is a live execution/credential surface.

Overview
Adds OrcaRouter as a first-class reseller provider (same shape as OpenRouter): models appear in the Agent combobox as orcarouter/<id>, and inference goes through the OpenAI-compatible gateway at https://api.orcarouter.ai/v1.

A public catalog route lists chat-capable models (no key required to list). Execution supports streaming, the tool loop, and structured output via json_object (native json_schema is disabled to avoid upstream 400s). Attachments allow images and PDFs.

Keys resolve via workspace/org BYOK or a user-supplied key. Docs and env/schema wiring mention the new provider.

Reviewed by Cursor Bugbot for commit 3cafb60. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds OrcaRouter as an OpenAI-compatible named provider, including model discovery, execution and tool-loop support, BYOK registration, dynamic model-store integration, attachment metadata, contracts, tests, and documentation.

  • Registers OrcaRouter across provider types, registries, model resolution, stores, and the model picker.
  • Adds a public model-catalog route and an OpenAI-compatible provider implementation with streaming, tools, and structured-output fallback.
  • Adds workspace and organization BYOK support plus environment configuration.

Confidence Score: 4/5

The self-hosted environment-key fallback must be wired into OrcaRouter key resolution before merging; the remaining typing issue is non-blocking.

Self-hosted executions configured only through ORCAROUTER_API_KEY deterministically fail because the new resolver never reads that variable, while the provider requires the resolved request key.

Files Needing Attention: apps/sim/lib/api-key/byok.ts; apps/sim/providers/orcarouter/index.ts; apps/sim/providers/orcarouter/utils.ts

Important Files Changed

Filename Overview
apps/sim/lib/api-key/byok.ts Adds OrcaRouter BYOK resolution but omits the declared environment-key fallback, breaking documented self-hosted inference configuration.
apps/sim/providers/orcarouter/index.ts Implements OrcaRouter inference, streaming, structured output, and tool loops; behavior broadly follows OpenRouter, but the new code contains several prohibited any boundaries.
apps/sim/app/api/providers/orcarouter/models/route.ts Adds public model discovery, chat-capability filtering, provider prefixing, blacklist handling, caching, and contract-shaped responses.
apps/sim/providers/models.ts Registers OrcaRouter as a dynamic reseller provider and adds runtime catalog synchronization.
apps/sim/app/workspace/[workspaceId]/providers/provider-models-loader.tsx Loads OrcaRouter models into both provider definitions and the workspace provider store.
apps/sim/lib/api/contracts/providers.ts Adds the typed client contract for the OrcaRouter model-catalog route.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Catalog[OrcaRouter /v1/models] --> Route[Model catalog route]
  Route --> Query[Provider models query]
  Query --> Store[Providers store]
  Store --> Picker[Agent model picker]
  Picker --> Resolver[Provider and API-key resolution]
  BYOK[Workspace or organization BYOK] --> Resolver
  Env[ORCAROUTER_API_KEY] -. missing fallback .-> Resolver
  Resolver --> Provider[OrcaRouter provider]
  Provider --> API[OrcaRouter chat completions]
  Provider --> Tools[Sim tool execution loop]
Loading

Reviews (1): Last reviewed commit: "feat(providers): add OrcaRouter as a nam..." | Re-trigger Greptile

Comment on lines +325 to +344
const isOrcaRouterModel =
provider === 'orcarouter' ||
useProvidersStore.getState().providers.orcarouter.models.includes(model)
if (isOrcaRouterModel) {
if (workspaceId) {
const byokResult = await getBYOKKey(workspaceId, 'orcarouter')
if (byokResult) {
logger.info('Using BYOK key for OrcaRouter', {
model,
workspaceId,
scope: byokResult.scope,
})
return byokResult
}
}
if (userProvidedKey) {
return { apiKey: userProvidedKey, isBYOK: false }
}
throw new Error(`API key is required for OrcaRouter ${model}`)
}

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.

P1 Environment key fallback is skipped

When a self-hosted deployment configures ORCAROUTER_API_KEY without a workspace BYOK or per-block key, this branch throws instead of using the documented environment fallback, causing every OrcaRouter inference request to fail with an API-key-required error.

Suggested change
const isOrcaRouterModel =
provider === 'orcarouter' ||
useProvidersStore.getState().providers.orcarouter.models.includes(model)
if (isOrcaRouterModel) {
if (workspaceId) {
const byokResult = await getBYOKKey(workspaceId, 'orcarouter')
if (byokResult) {
logger.info('Using BYOK key for OrcaRouter', {
model,
workspaceId,
scope: byokResult.scope,
})
return byokResult
}
}
if (userProvidedKey) {
return { apiKey: userProvidedKey, isBYOK: false }
}
throw new Error(`API key is required for OrcaRouter ${model}`)
}
const isOrcaRouterModel =
provider === 'orcarouter' ||
useProvidersStore.getState().providers.orcarouter.models.includes(model)
if (isOrcaRouterModel) {
if (workspaceId) {
const byokResult = await getBYOKKey(workspaceId, 'orcarouter')
if (byokResult) {
logger.info('Using BYOK key for OrcaRouter', {
model,
workspaceId,
scope: byokResult.scope,
})
return byokResult
}
}
if (userProvidedKey) {
return { apiKey: userProvidedKey, isBYOK: false }
}
if (env.ORCAROUTER_API_KEY) {
return { apiKey: env.ORCAROUTER_API_KEY, isBYOK: false }
}
throw new Error(`API key is required for OrcaRouter ${model}`)
}

Comment on lines +48 to +53
targetPayload: any,
messages: any[],
responseFormat: any,
model: string
): Promise<any[]> {
const useNative = await supportsNativeStructuredOutputs(model)

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.

P2 Provider boundaries use explicit any

The new provider uses any across response-format payloads, request payloads, error metadata, and forced-tool responses, bypassing the repository's type-safety requirement and preventing TypeScript from detecting incompatible provider fields or unsafe property access as the API evolves.

Context Used: TypeScript conventions and type safety (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3cafb60. Configure here.

(contentType === 'video' && BEDROCK_VIDEO_FORMATS.has(extension))
)
case 'openrouter':
case 'orcarouter':

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PDF attachments formatted incorrectly

High Severity

orcarouter is registered for image and PDF attachments like OpenRouter, but formatMessagesForProvider only routes OpenRouter through buildOpenRouterMessageContent. OrcaRouter falls through to buildOpenAICompatibleChatContent, which sends every attachment as image_url, so PDFs never become file parts and multimodal document runs fail or misbehave.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3cafb60. Configure here.

return { apiKey: userProvidedKey, isBYOK: false }
}
throw new Error(`API key is required for OrcaRouter ${model}`)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Env API key never used

Medium Severity

ORCAROUTER_API_KEY is documented as a self-hosted fallback for inference, and similar BYOK resellers (together, baseten, fireworks) fall back to their env keys after BYOK and the block key. The new OrcaRouter branch only tries BYOK then the user-provided key, then throws, so a configured env key alone never authorizes requests.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3cafb60. Configure here.

Comment thread apps/sim/blocks/utils.ts
...vllmModels,
...litellmModels,
...openrouterModels,
...orcarouterModels,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot mock missing provider

Medium Severity

getModelOptions now reads providers.orcarouter.models, but the copilot metadata fallback mock still omits orcarouter. When that mock replaces the store, option resolution throws, is caught, and Agent model options come back empty for copilot.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3cafb60. Configure here.

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