Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ Advanced and source-build guides:
| Z.AI GLM Coding Plan | `/provider` or OpenAI-compatible env vars | Uses `OPENAI_API_KEY` at `https://api.z.ai/api/coding/paas/v4` and defaults to `glm-5.2` |
| AI/ML API | `/provider` or `AIMLAPI_API_KEY` ([setup guide](docs/aimlapi-setup.md)) | Uses `https://api.aimlapi.com/v1`, auto-detects the OpenAI-compatible route from `AIMLAPI_API_KEY`, sends OpenClaude attribution headers, and discovers chat-capable models from the public `/models` catalog |
| ApiSmart | `/provider` or `APISMART_API_KEY` | Uses `https://gw.apismart.ai/v1`, defaults to `DEEPSEEK_V4_FLASH`, and supports optional `APISMART_MODEL` plus authenticated model discovery |
| OrcaRouter | `/provider` or `ORCAROUTER_API_KEY` | OpenAI-compatible model routing gateway at `https://api.orcarouter.ai/v1`, defaults to `openai/gpt-5.5`, with `orcarouter/auto` smart routing and authenticated model discovery |
| Hicap | `/provider` or OpenAI-compatible env vars | Uses `api-key` auth, discovers models from unauthenticated `/models`, and supports Responses mode for `gpt-` models |
| Fireworks AI | `/provider` or env vars | First-class provider with 276 curated models (DeepSeek, Qwen, Llama, Gemma, and more); uses `FIREWORKS_API_KEY` |
| LongCat | `/provider` or env vars | Meituan LongCat OpenAI-compatible API at `https://api.longcat.chat/openai/v1`; uses `LONGCAT_API_KEY` and defaults to `LongCat-2.0` |
Expand Down
1 change: 1 addition & 0 deletions src/integrations/compatibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const EXPECTED_PRESETS = [
'hicap',
'azure-openai',
'openrouter',
'orcarouter',
'lmstudio',
'dashscope-cn',
'dashscope-intl',
Expand Down
27 changes: 27 additions & 0 deletions src/integrations/gateways/orcarouter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { describe, expect, test } from 'bun:test'

import orcarouter from './orcarouter.js'

describe('orcarouter gateway', () => {
test('uses hybrid discovery with dedicated credentials', () => {
expect(orcarouter.id).toBe('orcarouter')
expect(orcarouter.catalog?.source).toBe('hybrid')
expect(orcarouter.catalog?.discovery?.kind).toBe('openai-compatible')
expect(orcarouter.setup.dedicatedCredentialsOnly).toBe(true)
expect(orcarouter.setup.credentialEnvVars).toEqual(['ORCAROUTER_API_KEY'])
expect(orcarouter.defaultBaseUrl).toBe('https://api.orcarouter.ai/v1')
expect(orcarouter.defaultModel).toBe('openai/gpt-5.5')
})

test('curated catalog exposes auto routing plus flagship models', () => {
const models = orcarouter.catalog?.models ?? []
expect(models.some(model => model.apiName === 'orcarouter/auto')).toBe(true)
expect(models.some(model => model.apiName === 'openai/gpt-5.5')).toBe(true)
expect(
models.some(model => model.apiName === 'anthropic/claude-sonnet-4.6'),
).toBe(true)
expect(
models.some(model => model.apiName === 'google/gemini-3.5-flash'),
).toBe(true)
})
})
65 changes: 65 additions & 0 deletions src/integrations/gateways/orcarouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { defineGateway } from '../define.js'

export default defineGateway({
id: 'orcarouter',
label: 'OrcaRouter',
category: 'aggregating',
defaultBaseUrl: 'https://api.orcarouter.ai/v1',
defaultModel: 'openai/gpt-5.5',
supportsModelRouting: true,
setup: {
requiresAuth: true,
authMode: 'api-key',
credentialEnvVars: ['ORCAROUTER_API_KEY'],
dedicatedCredentialsOnly: true,
},
startup: {
probeReadiness: 'openai-compatible-models',
},
transportConfig: {
kind: 'openai-compatible',
openaiShim: {
supportsAuthHeaders: true,
},
},
preset: {
id: 'orcarouter',
description: 'OrcaRouter OpenAI-compatible endpoint',
apiKeyEnvVars: ['ORCAROUTER_API_KEY'],
vendorId: 'openai',
},
catalog: {
source: 'hybrid',
discovery: { kind: 'openai-compatible' },
discoveryCacheTtl: '1d',
discoveryRefreshMode: 'background-if-stale',
allowManualRefresh: true,
models: [
{
id: 'orcarouter-auto',
apiName: 'orcarouter/auto',
label: 'Auto — Smart Routing (via OrcaRouter)',
notes: 'Gateway routes to the best model for each request',
},
{
id: 'orcarouter-gpt-5.5',
apiName: 'openai/gpt-5.5',
label: 'GPT-5.5 (via OrcaRouter)',
modelDescriptorId: 'gpt-5.5',
},
{
id: 'orcarouter-claude-sonnet-4-6',
apiName: 'anthropic/claude-sonnet-4.6',
label: 'Claude Sonnet 4.6 (via OrcaRouter)',
modelDescriptorId: 'claude-sonnet-4-6',
},
{
id: 'orcarouter-gemini-3.5-flash',
apiName: 'google/gemini-3.5-flash',
label: 'Gemini 3.5 Flash (via OrcaRouter)',
modelDescriptorId: 'gemini-3.5-flash',
},
],
},
usage: { supported: false },
})
3 changes: 2 additions & 1 deletion src/integrations/generated/integrationArtifacts.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import gatewayOllama from '../gateways/ollama.js'
import gatewayOpencodeGo from '../gateways/opencode-go.js'
import gatewayOpencode from '../gateways/opencode.js'
import gatewayOpenrouter from '../gateways/openrouter.js'
import gatewayOrcarouter from '../gateways/orcarouter.js'
import gatewayTogether from '../gateways/together.js'
import gatewayVertex from '../gateways/vertex.js'
import gatewayXiaomiMimoToken from '../gateways/xiaomi-mimo-token.js'
Expand Down Expand Up @@ -90,7 +91,7 @@ import modelXai from '../models/xai.js'
import modelXiaomiMimo from '../models/xiaomi-mimo.js'

export const VENDOR_DESCRIPTORS = [vendorAnthropic, vendorBankr, vendorDeepseek, vendorFireworks, vendorGemini, vendorLongcat, vendorMinimax, vendorMoonshot, vendorNearai, vendorOpenai, vendorVenice, vendorXai, vendorXiaomiMimo, vendorZai] as const satisfies readonly VendorDescriptor[]
export const GATEWAY_DESCRIPTORS = [gatewayAimlapi, gatewayApismart, gatewayAtlasCloud, gatewayAtomicChat, gatewayAzureOpenai, gatewayBedrock, gatewayClinepass, gatewayCloudflare, gatewayCustom, gatewayDashscopeCn, gatewayDashscopeIntl, gatewayGithubEnterprise, gatewayGithub, gatewayGitlawbOpengateway, gatewayGroq, gatewayHicap, gatewayKimiCode, gatewayLmstudio, gatewayMistral, gatewayNvidiaNim, gatewayOllama, gatewayOpencodeGo, gatewayOpencode, gatewayOpenrouter, gatewayTogether, gatewayVertex, gatewayXiaomiMimoToken] as const satisfies readonly GatewayDescriptor[]
export const GATEWAY_DESCRIPTORS = [gatewayAimlapi, gatewayApismart, gatewayAtlasCloud, gatewayAtomicChat, gatewayAzureOpenai, gatewayBedrock, gatewayClinepass, gatewayCloudflare, gatewayCustom, gatewayDashscopeCn, gatewayDashscopeIntl, gatewayGithubEnterprise, gatewayGithub, gatewayGitlawbOpengateway, gatewayGroq, gatewayHicap, gatewayKimiCode, gatewayLmstudio, gatewayMistral, gatewayNvidiaNim, gatewayOllama, gatewayOpencodeGo, gatewayOpencode, gatewayOpenrouter, gatewayOrcarouter, gatewayTogether, gatewayVertex, gatewayXiaomiMimoToken] as const satisfies readonly GatewayDescriptor[]
export const ANTHROPIC_PROXY_DESCRIPTORS = [anthropicproxyCustom] as const satisfies readonly AnthropicProxyDescriptor[]
export const BRAND_DESCRIPTORS = [brandClaude, brandDeepseek, brandFireworks, brandGemini, brandGlm, brandGpt, brandKimi, brandLing, brandLlama, brandLongcat, brandMacaron, brandMinimax, brandMistral, brandNearai, brandNemotron, brandOpenaiCompatibleAlias, brandQwen, brandTencent, brandXai, brandXiaomiMimo] as const satisfies readonly BrandDescriptor[]
export const MODEL_DESCRIPTOR_GROUPS = [modelClaude, modelDeepseek, modelFireworksMerged, modelGemini, modelGlm, modelGpt, modelKimi, modelLing, modelLlama, modelLongcat, modelMacaron, modelMinimax, modelMistral, modelNearai, modelNemotron, modelOpenaiCompatibleAlias, modelOpencode, modelQwen, modelTencent, modelXai, modelXiaomiMimo] as const satisfies readonly (readonly ModelDescriptor[])[]
Expand Down
12 changes: 12 additions & 0 deletions src/integrations/generated/integrationManifest.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,17 @@ export const PROVIDER_PRESET_MANIFEST = [
"OPENROUTER_API_KEY"
]
},
{
"preset": "orcarouter",
"routeKind": "gateway",
"routeId": "orcarouter",
"vendorId": "openai",
"gatewayId": "orcarouter",
"description": "OrcaRouter OpenAI-compatible endpoint",
"apiKeyEnvVars": [
"ORCAROUTER_API_KEY"
]
},
{
"preset": "together",
"routeKind": "gateway",
Expand Down Expand Up @@ -567,6 +578,7 @@ export const ORDERED_PROVIDER_PRESETS = [
"opencode-go",
"opencode",
"openrouter",
"orcarouter",
"together",
"venice",
"xai",
Expand Down
3 changes: 3 additions & 0 deletions src/integrations/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ describe('loaded registry validation', () => {
// Virtual model — the gateway's smart router resolves it server-side,
// so there is no concrete model descriptor to reference.
'gitlawb-opengateway:opengateway-auto',
// Virtual model — OrcaRouter's `orcarouter/auto` router resolves the
// serving model server-side, so there is no concrete descriptor.
'orcarouter:orcarouter-auto',
// Cloudflare Workers AI serves provider-specific quantized builds
// (`@cf/...`) with no shared cross-provider model descriptor, the same
// situation as azure-deployment above. See gateways/cloudflare.ts (#1100).
Expand Down
1 change: 1 addition & 0 deletions src/utils/envFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const ALLOWED_ENV_FILE_KEYS = new Set([
'OPENGATEWAY_BASE_URL',
'OPENCLAUDE_OLLAMA_NUM_CTX',
'OPENROUTER_API_KEY',
'ORCAROUTER_API_KEY',
'OPENAI_API_BASE',
'OPENAI_API_FORMAT',
'OPENAI_API_KEYS',
Expand Down
8 changes: 8 additions & 0 deletions web/src/data/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ export const providers: Provider[] = [
envVars: ['OPENROUTER_API_KEY'],
notes: 'OpenAI-compatible aggregation across hundreds of hosted models.',
},
{
id: 'orcarouter',
name: 'OrcaRouter',
group: 'gateways',
setup: '/provider or env vars',
envVars: ['ORCAROUTER_API_KEY'],
notes: 'OpenAI-compatible model routing gateway with named auto routing.',
},
{
id: 'near-ai',
name: 'NEAR AI',
Expand Down
Loading