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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ DEEPSEEK_API_KEY / DEEPSEEK_BASE_URL / DEEPSEEK_DEFAULT_MODEL
MINIMAX_API_KEY / MINIMAX_BASE_URL / MINIMAX_MODEL
QWEN_API_KEY or DASHSCOPE_API_KEY / QWEN_BASE_URL / QWEN_MODEL
OPENROUTER_API_KEY / OPENROUTER_BASE_URL / OPENROUTER_MODEL
REQUESTY_API_KEY / REQUESTY_BASE_URL / REQUESTY_DEFAULT_MODEL
KIMI_API_KEY / KIMI_BASE_URL / KIMI_MODEL
GEMINI_API_KEY / GEMINI_BASE_URL / GEMINI_MODEL
IFLOW_API_KEY / IFLOW_BASE_URL / IFLOW_MODEL
Expand Down Expand Up @@ -257,7 +258,7 @@ OpenAI-compatible runtime adapter:

- CodexBridge can expose non-OpenAI providers through a local Responses adapter while Codex app-server still talks to a Responses-shaped endpoint.
- The adapter now handles `/responses/compact`, Chat Completions conversion, stream error mapping, CLIProxyAPI top-level stream error chunks, stream read failure framing, configured transient upstream retry, usage fallback including Gemini-family `usageMetadata`, provider/model thinking policy, CLIProxyAPI-style payload compatibility (`default`, `default-raw`/`defaultRaw`, `override`, `override-raw`/`overrideRaw`, `filter`, `root`, protocol/model matching), multimodal input capability flags, and model capability metadata.
- DeepSeek, MiniMax, Qwen, OpenRouter, Kimi, Gemini, and iFlow are loaded as `providerKind: openai-compatible`; they differ by env vars and capability presets only, not separate provider plugin classes.
- DeepSeek, MiniMax, Qwen, OpenRouter, Requesty, Kimi, Gemini, and iFlow are loaded as `providerKind: openai-compatible`; they differ by env vars and capability presets only, not separate provider plugin classes.
- The model capability catalog follows the same direction as CLIProxyAPI: model quirks are represented as data (`thinking`, `payload`, tool support, multimodal support, token caps), while the executor stays generic.
- Current built-in catalog covers the CLIProxyAPI model families used by Codex-style routing: Codex, DeepSeek, MiniMax, Qwen, iFlow, Kimi, OpenRouter, Gemini/AI Studio/Vertex, Claude, and Antigravity. `*_MODEL_CATALOG_PATH` can also point at a CLIProxyAPI `models.json`-shaped catalog object; CodexBridge flattens it and merges model token/thinking metadata into runtime capabilities. Native auth/header systems from CLIProxyAPI are not copied into this adapter; use provider env vars or the custom `CODEX_COMPAT_*` profile for deployment-specific credentials.
- Auth pools, proxy rotation, and custom provider header management remain deployment-layer concerns and are intentionally separate from the generic OpenAI-compatible adapter.
Expand Down Expand Up @@ -290,7 +291,7 @@ CODEX_COMPAT_PROVIDER_ID=custom
CODEX_COMPAT_API_KEY=...
CODEX_COMPAT_BASE_URL=https://provider.example/v1
CODEX_COMPAT_DEFAULT_MODEL=example-model
CODEX_COMPAT_CAPABILITIES=default # or deepseek/minimax/qwen/kimi/gemini/iflow/openrouter
CODEX_COMPAT_CAPABILITIES=default # or deepseek/minimax/qwen/kimi/gemini/iflow/openrouter/requesty
CODEX_COMPAT_REQUEST_RETRY=2
```

Expand Down Expand Up @@ -564,7 +565,7 @@ That file is the stable place to adjust:

- `WEIXIN_ACCOUNT_ID`
- `CODEX_DEFAULT_PROVIDER_PROFILE_ID`
- optional OpenAI-compatible provider keys such as `DEEPSEEK_*`, `MINIMAX_*`, `QWEN_*`, `OPENROUTER_*`, or `CODEX_COMPAT_*`
- optional OpenAI-compatible provider keys such as `DEEPSEEK_*`, `MINIMAX_*`, `QWEN_*`, `OPENROUTER_*`, `REQUESTY_*`, or `CODEX_COMPAT_*`
- `CODEXBRIDGE_DEBUG_WEIXIN`

### Windows Scheduled Task
Expand Down
8 changes: 8 additions & 0 deletions packages/codex-provider-relay/docs/LIVE_SMOKE_RECIPES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ export EMBEDDINGS_API_ENDPOINT=https://openrouter.ai/api/v1/embeddings
export EMBEDDINGS_MODEL=qwen/qwen3-embedding-8b
```

Requesty is an OpenAI-compatible gateway and can be smoke-tested the same way (`provider/model` naming):

```bash
export REQUESTY_API_KEY=...
export REQUESTY_BASE_URL=https://router.requesty.ai/v1
export REQUESTY_DEFAULT_MODEL=openai/gpt-4o-mini
```

The embedding endpoint/model are defaults only. Any OpenAI-compatible embeddings API can be used.

## Smoke 1: Mixed Runtime
Expand Down
25 changes: 25 additions & 0 deletions packages/codex-provider-relay/docs/RECIPES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ const runtime = new CodexProviderRuntime({
});
```

## Mixed Requesty Runtime

Requesty is an OpenAI-compatible LLM gateway. Wire it exactly like OpenRouter, swapping the base URL, provider label, and API key env var. Models use `provider/model` naming (for example `openai/gpt-4o-mini`).

```ts
const runtime = new CodexProviderRuntime({
apiKey: process.env.REQUESTY_API_KEY!,
upstreamBaseUrl: "https://router.requesty.ai/v1",
defaultModel: "openai/gpt-4o-mini",
providerLabel: "requesty",
profileMode: "mixed",
toolStrategy: "codex-local-first",
});
```

## Relay-Emulated Hosted Tools

Relay-emulated tools must be declared and registered.
Expand Down Expand Up @@ -71,6 +86,16 @@ CODEX_PROVIDER_RELAY_TRACE=stderr-json
codex-provider-server
```

The same shape works for the `requesty` preset (base `https://router.requesty.ai/v1`):

```bash
CODEX_PROVIDER_RELAY_CAPABILITY_PRESET=requesty
CODEX_PROVIDER_RELAY_API_KEY=...
CODEX_PROVIDER_RELAY_MODEL=openai/gpt-4o-mini
CODEX_PROVIDER_RELAY_TRACE=stderr-json
codex-provider-server
```

Legacy `CODEX_GATEWAY_*` variables remain supported for compatibility.

## Release Validation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type OpenAICompatibleCapabilityPresetId =
| 'minimax'
| 'qwen'
| 'openrouter'
| 'requesty'
| 'iflow'
| 'kimi'
| 'antigravity'
Expand Down Expand Up @@ -151,6 +152,15 @@ const PRESETS: Record<OpenAICompatibleCapabilityPresetId, OpenAICompatibleProvid
ownedBy: 'openrouter',
categories: ['openrouter'],
}),
requesty: buildPreset({
id: 'requesty',
displayName: 'Requesty',
apiKeyEnv: 'REQUESTY_API_KEY',
baseUrl: 'https://router.requesty.ai/v1',
defaultModel: 'openai/gpt-4o-mini',
ownedBy: 'requesty',
categories: ['requesty'],
}),
iflow: buildPreset({
id: 'iflow',
displayName: 'iFlow',
Expand Down Expand Up @@ -298,6 +308,10 @@ export const OPENAI_COMPATIBLE_PROFILE_PRESET_REGISTRATIONS: readonly OpenAIComp
presetId: 'openrouter',
envPrefix: 'OPENROUTER',
},
{
presetId: 'requesty',
envPrefix: 'REQUESTY',
},
{
presetId: 'kimi',
envPrefix: 'KIMI',
Expand Down Expand Up @@ -798,6 +812,7 @@ function normalizePresetId(id: string | null | undefined): OpenAICompatibleCapab
case 'minimax':
case 'qwen':
case 'openrouter':
case 'requesty':
case 'iflow':
case 'kimi':
case 'antigravity':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export type CliproxyModelCategory =
| 'antigravity'
| 'minimax-codex'
| 'deepseek-codex'
| 'openrouter';
| 'openrouter'
| 'requesty';

export interface CliproxyModelCatalogEntry {
category: CliproxyModelCategory;
Expand Down Expand Up @@ -152,6 +153,7 @@ const DIRECT_COMPAT_MODELS: CliproxyModelCatalogEntry[] = [
model('deepseek-codex', 'deepseek-v4-flash', 'deepseek', 'DeepSeek V4 Flash', null, { maxOutputTokens: 65536 }),
model('deepseek-codex', 'deepseek-v4-pro', 'deepseek', 'DeepSeek V4 Pro', null, { maxOutputTokens: 65536 }),
model('openrouter', 'openai/gpt-4o-mini', 'openrouter', 'OpenAI GPT-4o Mini', null, { maxOutputTokens: 16384 }),
model('requesty', 'openai/gpt-4o-mini', 'requesty', 'OpenAI GPT-4o Mini', null, { maxOutputTokens: 16384 }),
];

export const CLIPROXY_COMPAT_MODEL_CATALOG: CliproxyModelCatalogEntry[] = [
Expand Down
4 changes: 4 additions & 0 deletions test/providers/openai_compatible/live_provider_smoke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const PROVIDERS: LiveProviderSpec[] = [{
profileId: 'openrouter',
name: 'OpenRouter',
apiKeyEnvHint: ['OPENROUTER_API_KEY'],
}, {
profileId: 'requesty',
name: 'Requesty',
apiKeyEnvHint: ['REQUESTY_API_KEY'],
}];

for (const provider of PROVIDERS) {
Expand Down