converse-mcp-server 3.2.4 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +3 -3
- package/README.md +43 -8
- package/docs/API.md +7 -5
- package/docs/PROVIDERS.md +8 -5
- package/package.json +16 -16
- package/src/config.js +2 -2
- package/src/providers/codex.js +117 -31
- package/src/providers/gemini-cli.js +28 -29
- package/src/providers/google.js +36 -3
- package/src/utils/modelRouting.js +5 -3
package/.env.example
CHANGED
|
@@ -80,9 +80,9 @@ OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
|
80
80
|
# WARNING: Interactive policies may cause hangs in server/headless mode
|
|
81
81
|
# CODEX_APPROVAL_POLICY=never
|
|
82
82
|
|
|
83
|
-
# Default Codex model (default: gpt-
|
|
84
|
-
# Options: gpt-
|
|
85
|
-
# CODEX_MODEL=gpt-
|
|
83
|
+
# Default Codex backend model (default: gpt-6-astra). Per-request override: models: ["codex:<model>"]
|
|
84
|
+
# Options: gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.3-codex-spark
|
|
85
|
+
# CODEX_MODEL=gpt-6-astra
|
|
86
86
|
|
|
87
87
|
# ============================================
|
|
88
88
|
# Server Configuration
|
package/README.md
CHANGED
|
@@ -234,6 +234,7 @@ SUMMARIZATION_MODEL=gpt-5-nano # Default: gpt-5-nano
|
|
|
234
234
|
|
|
235
235
|
- **gemini-3.1-pro-preview** (aliases: `pro`, `gemini-pro`): Most advanced reasoning with expanded thinking levels (1M context, 64K output)
|
|
236
236
|
- **gemini-3.5-flash** (aliases: `gemini-3.5`, `flash-3.5`): Frontier-level agentic and coding performance at Flash speed (1M context, 65K output)
|
|
237
|
+
- **gemini-3.8-flash** (aliases: `gemini-3.8`, `flash-3.8`): Current-generation Flash with stronger long-horizon agentic performance (1M context, 65K output; thinking levels low/medium/high — no minimal)
|
|
237
238
|
- **gemini-2.5-pro** (alias: `pro 2.5`): Deep reasoning with thinking budget (1M context, 65K output)
|
|
238
239
|
- **gemini-2.5-flash** (alias: `flash`): Ultra-fast (1M context, 65K output)
|
|
239
240
|
- **gemini-2.5-flash-lite** (alias: `flash-lite`): Lightweight fast model (1M context, 65K output)
|
|
@@ -280,7 +281,9 @@ Any other model works via its full `provider/model` slug or the `openrouter:` na
|
|
|
280
281
|
|
|
281
282
|
### Codex Models
|
|
282
283
|
|
|
283
|
-
- **codex**: OpenAI Codex agentic coding assistant
|
|
284
|
+
- **codex**: OpenAI Codex agentic coding assistant (GPT-6 Astra by default)
|
|
285
|
+
- Pick another backend per request with `codex:<model>` (e.g. `codex:sol`, `codex:gpt-5.6-terra`) or globally with `CODEX_MODEL`; backends: `gpt-6-astra` (alias `astra`), `gpt-5.6-sol` (`sol`), `gpt-5.6-terra` (`terra`), `gpt-5.6-luna` (`luna`), `gpt-5.5`, `gpt-5.3-codex-spark` (`spark`)
|
|
286
|
+
- `reasoning_effort` maps onto the tiers the chosen backend accepts (GPT-6 Astra: `low` through `max`, no `none`)
|
|
284
287
|
- Thread-based sessions with persistent context
|
|
285
288
|
- Direct filesystem access from working directory
|
|
286
289
|
- Typical response time: 6-20 seconds (longer for complex tasks)
|
|
@@ -301,7 +304,7 @@ Reach these with the `copilot:` namespace (e.g. `copilot:gpt-5.6-terra`); uses y
|
|
|
301
304
|
|
|
302
305
|
- **OpenAI**: `gpt-5.6-sol` (aliases: `gpt-5.6`, `gpt-5`), `gpt-5.6-terra`, `gpt-5.6-luna` (all support `reasoning_effort`)
|
|
303
306
|
- **Anthropic**: `claude-fable-5` (alias: `fable`), `claude-sonnet-5` (alias: `sonnet`), `claude-opus-4.8` (aliases: `opus`, `claude`)
|
|
304
|
-
- **Google**: `gemini-3.1-pro-preview` (aliases: `gemini`, `gemini-3.1-pro`), `gemini-3.5-flash` (alias: `gemini-flash`)
|
|
307
|
+
- **Google**: `gemini-3.1-pro-preview` (aliases: `gemini`, `gemini-3.1-pro`), `gemini-3.8-flash` (aliases: `gemini-3.8`, `flash-3.8`), `gemini-3.5-flash` (alias: `gemini-flash`)
|
|
305
308
|
- Any other `copilot:<id>` is forwarded to the Copilot backend verbatim
|
|
306
309
|
|
|
307
310
|
## 📚 Help & Documentation
|
|
@@ -356,6 +359,7 @@ CODEX_API_KEY=your_codex_api_key_here # Optional if ChatGPT login availabl
|
|
|
356
359
|
CODEX_SANDBOX_MODE=read-only # read-only (default), workspace-write, danger-full-access
|
|
357
360
|
CODEX_SKIP_GIT_CHECK=true # true (default), false
|
|
358
361
|
CODEX_APPROVAL_POLICY=never # never (default), untrusted, on-failure, on-request
|
|
362
|
+
CODEX_MODEL=gpt-6-astra # gpt-6-astra (default), gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5
|
|
359
363
|
```
|
|
360
364
|
|
|
361
365
|
### Configuration Options
|
|
@@ -371,18 +375,42 @@ CODEX_APPROVAL_POLICY=never # never (default), untrusted, on-fa
|
|
|
371
375
|
|
|
372
376
|
These must be set in your system environment or when launching Claude Code, NOT in the project .env file:
|
|
373
377
|
|
|
374
|
-
| Variable
|
|
375
|
-
|
|
|
376
|
-
| `MAX_MCP_OUTPUT_TOKENS`
|
|
377
|
-
| `MCP_TOOL_TIMEOUT`
|
|
378
|
+
| Variable | Description | Default | Example |
|
|
379
|
+
| ------------------------------------ | ----------------------------------------------------------------------- | ------------------------------- | --------------------------- |
|
|
380
|
+
| `MAX_MCP_OUTPUT_TOKENS` | Token response limit | `25000` | `200000` |
|
|
381
|
+
| `MCP_TOOL_TIMEOUT` | Wall-clock limit per tool call (ms) | ~28 hours when unset | `7200000` (2 h) |
|
|
382
|
+
| `CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT` | Idle window (ms) — aborts a call that produces no output for this long | 30 min (stdio) / 5 min (HTTP) | `3600000` (60 min) |
|
|
378
383
|
|
|
379
384
|
```bash
|
|
380
385
|
# Example: Set globally before starting Claude Code
|
|
381
386
|
export MAX_MCP_OUTPUT_TOKENS=200000
|
|
382
|
-
export
|
|
387
|
+
export CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT=3600000 # 60 min for long silent agentic calls
|
|
383
388
|
claude # Then start Claude Code
|
|
384
389
|
```
|
|
385
390
|
|
|
391
|
+
Or persist them in `~/.claude/settings.json`:
|
|
392
|
+
|
|
393
|
+
```json
|
|
394
|
+
{
|
|
395
|
+
"env": {
|
|
396
|
+
"MAX_MCP_OUTPUT_TOKENS": "200000",
|
|
397
|
+
"CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT": "3600000"
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**The idle timeout is usually what kills long calls.** Agentic models (Codex, Claude Agent SDK) can work silently for 30+ minutes; Converse holds one MCP request open the whole time, and Claude Code aborts it after the idle window with an error like _"failed after 30 minutes of silence. The idle timeout aborted it."_ Progress-notification heartbeats can't prevent this — Claude Code doesn't send a `progressToken` on `tools/call`, so an MCP server has no spec-compliant way to emit them ([claude-code#58687](https://github.com/anthropics/claude-code/issues/58687)). Raising the idle window is the only fix.
|
|
403
|
+
|
|
404
|
+
#### Codex CLI Tool Timeout
|
|
405
|
+
|
|
406
|
+
If you register Converse in OpenAI's Codex CLI, note that Codex enforces its own **hard 300-second default** per MCP tool call (`tool_timeout_sec`, undocumented — it exists only in Codex's config schema). Progress notifications don't extend it. Raise it in `~/.codex/config.toml`:
|
|
407
|
+
|
|
408
|
+
```toml
|
|
409
|
+
[mcp_servers.converse]
|
|
410
|
+
# ... command/env ...
|
|
411
|
+
tool_timeout_sec = 3600 # default 300 kills long calls at 5 minutes
|
|
412
|
+
```
|
|
413
|
+
|
|
386
414
|
### Model Selection
|
|
387
415
|
|
|
388
416
|
Use `"auto"` for automatic model selection, or specify exact models:
|
|
@@ -421,7 +449,7 @@ Use `"auto"` for automatic model selection, or specify exact models:
|
|
|
421
449
|
Provider priority order (subscription-based SDK providers first, then API-key providers):
|
|
422
450
|
|
|
423
451
|
1. Codex (`codex`)
|
|
424
|
-
2. Gemini via Antigravity CLI (`gemini
|
|
452
|
+
2. Gemini via Antigravity CLI (`gemini` → Gemini 3.8 Flash, `gemini:pro`)
|
|
425
453
|
3. Claude Agent SDK (`claude` → Claude Fable 5)
|
|
426
454
|
4. Copilot (`copilot`)
|
|
427
455
|
5. OpenAI (`gpt-5.6`)
|
|
@@ -532,6 +560,13 @@ For development setup, see the [Development](#-development) section below.
|
|
|
532
560
|
|
|
533
561
|
- Clear cache and reinstall: `npm run clean`
|
|
534
562
|
|
|
563
|
+
**Long tool calls aborted mid-run (idle/timeout errors):**
|
|
564
|
+
|
|
565
|
+
- The abort almost always comes from the MCP _client_, not Converse — Converse's own limits are 30 min per provider call and 90 min per async job.
|
|
566
|
+
- Claude Code: raise `CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT` (idle window, default 30 min stdio / 5 min HTTP) and check `MCP_TOOL_TIMEOUT` (wall-clock). See [Claude Code Environment Variables](#claude-code-environment-variables-systemglobal).
|
|
567
|
+
- Codex CLI: set `tool_timeout_sec` under `[mcp_servers.converse]` in `~/.codex/config.toml` — the undocumented default is 300 seconds.
|
|
568
|
+
- Immune alternative: run the call with `async: true` and poll `check_status` — each poll is a fresh short request, so no client timeout applies.
|
|
569
|
+
|
|
535
570
|
### Debug Mode
|
|
536
571
|
|
|
537
572
|
```bash
|
package/docs/API.md
CHANGED
|
@@ -391,6 +391,7 @@ Provide models as plain name strings in the `models` array. Bare names and alias
|
|
|
391
391
|
|-------|---------|---------|--------|-------|
|
|
392
392
|
| `gemini-3.1-pro-preview` | `pro`, `gemini-pro` | 1M | 64K | Most advanced reasoning, expanded thinking levels |
|
|
393
393
|
| `gemini-3.5-flash` | `gemini-3.5`, `flash-3.5` | 1M | 65K | Frontier agentic/coding at Flash speed |
|
|
394
|
+
| `gemini-3.8-flash` | `gemini-3.8`, `flash-3.8` | 1M | 65K | Current-generation Flash; thinking low/medium/high only |
|
|
394
395
|
| `gemini-2.5-pro` | `pro 2.5` | 1M | 65K | Deep reasoning with thinking budget |
|
|
395
396
|
| `gemini-2.5-flash` | `flash` | 1M | 65K | Ultra-fast |
|
|
396
397
|
| `gemini-2.5-flash-lite` | `flash-lite` | 1M | 65K | Lightweight fast model |
|
|
@@ -455,12 +456,13 @@ Any other model works via its full `provider/model` slug (e.g. `anthropic/claude
|
|
|
455
456
|
|
|
456
457
|
**Codex** is an agentic coding assistant with direct filesystem access:
|
|
457
458
|
|
|
458
|
-
- **Model**: `codex` (underlying model: GPT-
|
|
459
|
+
- **Model**: `codex` (underlying model: GPT-6 Astra by default)
|
|
460
|
+
- **Backend selection**: `codex:<model>` per request (e.g. `codex:astra`, `codex:sol`, `codex:gpt-5.6-terra`), or `CODEX_MODEL` globally; unknown names pass through to the CLI verbatim
|
|
459
461
|
- **Thread-based sessions**: persistent conversation history via `continuation_id` in `chat` mode
|
|
460
462
|
- **Direct file access**: reads files from the working directory (paths relative to `CLIENT_CWD`)
|
|
461
463
|
- **Response times**: 6-20 seconds typical (complex tasks may take minutes)
|
|
462
464
|
- **Authentication**: ChatGPT login OR `CODEX_API_KEY` (NOT `OPENAI_API_KEY`)
|
|
463
|
-
- `reasoning_effort`
|
|
465
|
+
- `reasoning_effort` is clamped onto the tiers the chosen backend accepts (GPT-6 Astra: `low`–`max`, no `none`; GPT-5.6: `none`–`max`); web search is not applicable — Codex manages its own execution
|
|
464
466
|
|
|
465
467
|
### Claude Agent SDK (subscription)
|
|
466
468
|
|
|
@@ -476,7 +478,7 @@ Any other model works via its full `provider/model` slug (e.g. `anthropic/claude
|
|
|
476
478
|
|
|
477
479
|
The **Antigravity CLI** (`agy`) provides subscription-based access to Gemini models through Google OAuth:
|
|
478
480
|
|
|
479
|
-
- **Models** (text-only): `gemini` (= `gemini:
|
|
481
|
+
- **Models** (text-only): `gemini` (= `gemini:flash`, Gemini 3.8 Flash), `gemini:pro` (Gemini 3.1 Pro)
|
|
480
482
|
- **Authentication**: Google OAuth via `agy` (one-time interactive login)
|
|
481
483
|
- **Setup**: install the Antigravity CLI and run `agy` once to log in
|
|
482
484
|
- **Billing**: uses your Antigravity subscription/compute allowance instead of API credits
|
|
@@ -502,7 +504,7 @@ Reach these with the `copilot:` namespace (e.g. `copilot:gpt-5.6-terra`); uses y
|
|
|
502
504
|
|
|
503
505
|
- **OpenAI**: `gpt-5.6-sol` (aliases: `gpt-5.6`, `gpt-5`), `gpt-5.6-terra`, `gpt-5.6-luna` (all accept `reasoning_effort`)
|
|
504
506
|
- **Anthropic**: `claude-fable-5` (alias: `fable`), `claude-sonnet-5` (alias: `sonnet`), `claude-opus-5` (aliases: `opus`, `claude`), `claude-opus-4.8`
|
|
505
|
-
- **Google**: `gemini-3.1-pro-preview` (aliases: `gemini`, `gemini-3.1-pro`), `gemini-3.5-flash` (alias: `gemini-flash`)
|
|
507
|
+
- **Google**: `gemini-3.1-pro-preview` (aliases: `gemini`, `gemini-3.1-pro`), `gemini-3.8-flash` (aliases: `gemini-3.8`, `flash-3.8`), `gemini-3.5-flash` (alias: `gemini-flash`)
|
|
506
508
|
- Any other `copilot:<id>` is forwarded to the Copilot backend verbatim
|
|
507
509
|
|
|
508
510
|
### Model Selection
|
|
@@ -522,7 +524,7 @@ Use `"auto"` for automatic selection, or specify exact models:
|
|
|
522
524
|
"opus" // Anthropic API (-> claude-opus-5)
|
|
523
525
|
"claude" // Claude Agent SDK (-> Claude Fable 5)
|
|
524
526
|
"claude:opus" // Claude Agent SDK (Claude Opus 5)
|
|
525
|
-
"gemini" // Antigravity CLI (Gemini 3.
|
|
527
|
+
"gemini" // Antigravity CLI (Gemini 3.8 Flash)
|
|
526
528
|
"copilot:gpt-5.6-terra" // GitHub Copilot SDK
|
|
527
529
|
```
|
|
528
530
|
|
package/docs/PROVIDERS.md
CHANGED
|
@@ -24,6 +24,7 @@ This guide documents all supported AI providers in the Converse MCP Server and t
|
|
|
24
24
|
- **Supported Models**:
|
|
25
25
|
- `gemini-3.1-pro-preview` (aliases: `pro`, `gemini-pro`) - Most advanced reasoning with expanded thinking levels (1M context, 64K output)
|
|
26
26
|
- `gemini-3.5-flash` (aliases: `gemini-3.5`, `flash-3.5`) - Frontier-level agentic and coding performance at Flash speed (1M context, 65K output)
|
|
27
|
+
- `gemini-3.8-flash` (aliases: `gemini-3.8`, `flash-3.8`) - Current-generation Flash with stronger long-horizon agentic performance (1M context, 65K output; thinking levels low/medium/high — no minimal)
|
|
27
28
|
- `gemini-2.5-pro` (alias: `pro 2.5`) - Deep reasoning with thinking budget (1M context, 65K output)
|
|
28
29
|
- `gemini-2.5-flash` (alias: `flash`) - Ultra-fast model with thinking budget (1M context, 65K output)
|
|
29
30
|
- `gemini-2.5-flash-lite` (alias: `flash-lite`) - Lightweight fast model (1M context, 65K output)
|
|
@@ -100,9 +101,11 @@ This guide documents all supported AI providers in the Converse MCP Server and t
|
|
|
100
101
|
- `CODEX_SANDBOX_MODE` - Filesystem access control (default: read-only)
|
|
101
102
|
- `CODEX_SKIP_GIT_CHECK` - Skip Git repository validation (default: true)
|
|
102
103
|
- `CODEX_APPROVAL_POLICY` - Command approval behavior (default: never)
|
|
103
|
-
- `CODEX_MODEL` - Underlying model for Codex sessions (default: gpt-
|
|
104
|
+
- `CODEX_MODEL` - Underlying model for Codex sessions (default: gpt-6-astra; e.g. gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5)
|
|
104
105
|
- **Supported Models**:
|
|
105
|
-
- `codex` - OpenAI Codex agentic coding assistant (GPT-
|
|
106
|
+
- `codex` - OpenAI Codex agentic coding assistant (GPT-6 Astra by default)
|
|
107
|
+
- `codex:<model>` - Same, with an explicit backend: `codex:astra`, `codex:sol`, `codex:terra`, `codex:luna`, `codex:gpt-5.5`, `codex:spark`, or any slug the Codex CLI knows
|
|
108
|
+
- `reasoning_effort` is clamped onto what the backend accepts (GPT-6 Astra: `low`–`max`, no `none`)
|
|
106
109
|
- Thread-based sessions with persistent context
|
|
107
110
|
- Direct filesystem access from working directory
|
|
108
111
|
- Typical response time: 6-20 seconds (longer for complex tasks)
|
|
@@ -129,8 +132,8 @@ This guide documents all supported AI providers in the Converse MCP Server and t
|
|
|
129
132
|
2. Authenticate: run `agy` once interactively and complete the Google OAuth login. This also establishes workspace trust for your home directory (the provider spawns each call in a per-call subdirectory under `~/.converse/agy-runs`).
|
|
130
133
|
- **Environment Variables**: None (the provider detects the `agy` binary on PATH or at the platform install location)
|
|
131
134
|
- **Supported Models** (text-only — print mode has no image input channel):
|
|
132
|
-
- `gemini` (= `gemini:
|
|
133
|
-
- `gemini:
|
|
135
|
+
- `gemini` (= `gemini:flash`) - Gemini 3.8 Flash (default)
|
|
136
|
+
- `gemini:pro` - Gemini 3.1 Pro
|
|
134
137
|
- `reasoning_effort` selects the variant: `low` → (Low), `medium` → (Medium) for Flash / (High) for Pro, `high`/`max` → (High); unset defaults to (High)
|
|
135
138
|
|
|
136
139
|
**Key Features:**
|
|
@@ -216,7 +219,7 @@ agy
|
|
|
216
219
|
- `copilot` - Uses Copilot's default or env-configured model
|
|
217
220
|
- OpenAI: `gpt-5.6-sol` (aliases: bare `gpt-5.6`, `gpt-5`), `gpt-5.6-terra` (recommended balanced tier), `gpt-5.6-luna`
|
|
218
221
|
- Anthropic: `claude-fable-5` (alias: `fable`), `claude-sonnet-5` (alias: `sonnet`), `claude-opus-5` (aliases: `opus`, `claude`), `claude-opus-4.8`
|
|
219
|
-
- Google: `gemini-3.1-pro-preview` (aliases: `gemini`, `gemini-3.1-pro`), `gemini-3.5-flash` (alias: `gemini-flash`)
|
|
222
|
+
- Google: `gemini-3.1-pro-preview` (aliases: `gemini`, `gemini-3.1-pro`), `gemini-3.8-flash` (aliases: `gemini-3.8`, `flash-3.8`), `gemini-3.5-flash` (alias: `gemini-flash`)
|
|
220
223
|
- **Reasoning**: The `gpt-5.6-sol`/`terra`/`luna` tiers accept `reasoning_effort`.
|
|
221
224
|
- **Explicit pass-through**: Any other `copilot:<id>` model string is forwarded to the Copilot backend verbatim, so IDs outside the curated list still work while the backend accepts them.
|
|
222
225
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "converse-mcp-server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Converse MCP Server - Converse with other LLMs with chat and consensus tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -93,28 +93,28 @@
|
|
|
93
93
|
".env.example"
|
|
94
94
|
],
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
97
|
-
"@anthropic-ai/sdk": "^0.
|
|
98
|
-
"@github/copilot-sdk": "^1.0.
|
|
99
|
-
"@google/genai": "^2.
|
|
100
|
-
"@lydell/node-pty": "1.2.0-beta.
|
|
101
|
-
"@mistralai/mistralai": "^2.
|
|
102
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
103
|
-
"@openai/codex-sdk": "^0.
|
|
96
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.261",
|
|
97
|
+
"@anthropic-ai/sdk": "^0.123.0",
|
|
98
|
+
"@github/copilot-sdk": "^1.0.11",
|
|
99
|
+
"@google/genai": "^2.21.0",
|
|
100
|
+
"@lydell/node-pty": "1.2.0-beta.15",
|
|
101
|
+
"@mistralai/mistralai": "^2.6.4",
|
|
102
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
103
|
+
"@openai/codex-sdk": "^0.153.3",
|
|
104
104
|
"cors": "^2.8.6",
|
|
105
105
|
"dotenv": "^17.4.2",
|
|
106
106
|
"express": "^5.2.1",
|
|
107
107
|
"lru-cache": "^11.5.2",
|
|
108
|
-
"nanoid": "^6.0.
|
|
109
|
-
"openai": "^
|
|
110
|
-
"p-limit": "^7.3.
|
|
111
|
-
"vite": "^8.
|
|
108
|
+
"nanoid": "^6.0.1",
|
|
109
|
+
"openai": "^7.10.0",
|
|
110
|
+
"p-limit": "^7.3.2",
|
|
111
|
+
"vite": "^8.2.2"
|
|
112
112
|
},
|
|
113
113
|
"devDependencies": {
|
|
114
|
-
"@vitest/coverage-v8": "^
|
|
114
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
115
115
|
"cross-env": "^10.1.0",
|
|
116
|
-
"eslint": "^10.
|
|
116
|
+
"eslint": "^10.10.0",
|
|
117
117
|
"rimraf": "^6.1.3",
|
|
118
|
-
"vitest": "^
|
|
118
|
+
"vitest": "^5.0.0"
|
|
119
119
|
}
|
|
120
120
|
}
|
package/src/config.js
CHANGED
|
@@ -280,9 +280,9 @@ const CONFIG_SCHEMA = {
|
|
|
280
280
|
},
|
|
281
281
|
CODEX_MODEL: {
|
|
282
282
|
type: 'string',
|
|
283
|
-
default: 'gpt-
|
|
283
|
+
default: 'gpt-6-astra',
|
|
284
284
|
description:
|
|
285
|
-
'Default Codex model (e.g., gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5)',
|
|
285
|
+
'Default Codex backend model (e.g., gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5)',
|
|
286
286
|
},
|
|
287
287
|
|
|
288
288
|
// Copilot configuration
|
package/src/providers/codex.js
CHANGED
|
@@ -17,35 +17,75 @@ import { debugLog, debugError } from '../utils/console.js';
|
|
|
17
17
|
import { ProviderError, ErrorCodes, StopReasons } from './interface.js';
|
|
18
18
|
import { normalizeExtendedPath } from '../utils/pathUtils.js';
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Every Codex reasoning tier, weakest to strongest. Used to clamp a requested
|
|
22
|
+
* tier onto the set a given backend model accepts.
|
|
23
|
+
*
|
|
24
|
+
* Codex also exposes 'ultra' above 'max', but that tier turns on automatic
|
|
25
|
+
* sub-agent delegation — a change in how the run executes, not just how deep
|
|
26
|
+
* it reasons — so nothing at the tool level maps to it and it is kept off the
|
|
27
|
+
* ladder so the clamp can never select it.
|
|
28
|
+
*/
|
|
29
|
+
const EFFORT_LADDER = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Backend models Codex can run, keyed by the slug passed to the CLI as
|
|
33
|
+
* --model. The reasoning tiers are the ones each model's API accepts, verified
|
|
34
|
+
* against the API's own rejection messages (gpt-6-astra: "Supported values
|
|
35
|
+
* are: 'low', 'medium', 'high', 'xhigh', and 'max'"). The SDK's
|
|
36
|
+
* ModelReasoningEffort type is the union across models, so the backend is the
|
|
37
|
+
* authority and requests are clamped per model.
|
|
38
|
+
*/
|
|
39
|
+
const CODEX_BACKEND_MODELS = {
|
|
40
|
+
'gpt-6-astra': {
|
|
41
|
+
aliases: ['astra', 'gpt-6', 'gpt6', 'gpt6-astra'],
|
|
42
|
+
contextWindow: 272000,
|
|
43
|
+
supportedEfforts: ['low', 'medium', 'high', 'xhigh', 'max'],
|
|
44
|
+
},
|
|
45
|
+
'gpt-5.6-sol': {
|
|
46
|
+
aliases: ['sol', 'gpt-5.6', 'gpt5.6', 'gpt-5.6-codex'],
|
|
47
|
+
contextWindow: 272000,
|
|
48
|
+
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
49
|
+
},
|
|
50
|
+
'gpt-5.6-terra': {
|
|
51
|
+
aliases: ['terra'],
|
|
52
|
+
contextWindow: 272000,
|
|
53
|
+
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
54
|
+
},
|
|
55
|
+
'gpt-5.6-luna': {
|
|
56
|
+
aliases: ['luna'],
|
|
57
|
+
contextWindow: 272000,
|
|
58
|
+
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
59
|
+
},
|
|
60
|
+
'gpt-5.5': {
|
|
61
|
+
aliases: ['gpt5.5'],
|
|
62
|
+
contextWindow: 272000,
|
|
63
|
+
supportedEfforts: ['low', 'medium', 'high', 'xhigh'],
|
|
64
|
+
},
|
|
65
|
+
'gpt-5.3-codex-spark': {
|
|
66
|
+
aliases: ['spark', 'codex-spark'],
|
|
67
|
+
contextWindow: 128000,
|
|
68
|
+
supportedEfforts: ['low', 'medium', 'high', 'xhigh'],
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const DEFAULT_BACKEND_MODEL = 'gpt-6-astra';
|
|
73
|
+
|
|
74
|
+
// The single user-facing model the router exposes. The backend model behind it
|
|
75
|
+
// comes from CODEX_MODEL, or from a `codex:<model>` spec.
|
|
21
76
|
const SUPPORTED_MODELS = {
|
|
22
77
|
codex: {
|
|
23
78
|
modelName: 'codex',
|
|
24
|
-
friendlyName: 'OpenAI Codex (GPT-
|
|
25
|
-
contextWindow:
|
|
79
|
+
friendlyName: 'OpenAI Codex (GPT-6 Astra)',
|
|
80
|
+
contextWindow: CODEX_BACKEND_MODELS[DEFAULT_BACKEND_MODEL].contextWindow,
|
|
26
81
|
maxOutputTokens: 128000,
|
|
27
82
|
supportsStreaming: true,
|
|
28
83
|
supportsImages: true, // Codex SDK 0.118+ supports images via --image (local_image input)
|
|
29
84
|
supportsWebSearch: false, // Codex accesses files directly, not web
|
|
30
|
-
// Reasoning tiers this model's backend actually accepts. GPT-5.6 dropped
|
|
31
|
-
// 'minimal' and added 'none', while the SDK's ModelReasoningEffort type
|
|
32
|
-
// still advertises the pre-5.6 set — the backend is the authority, so the
|
|
33
|
-
// accepted tiers are declared per model and requests are clamped onto them.
|
|
34
|
-
supportedEfforts: ['none', 'low', 'medium', 'high', 'xhigh'],
|
|
35
85
|
timeout: 1800000, // 30 minutes
|
|
36
86
|
description:
|
|
37
|
-
'OpenAI Codex agentic coding assistant with local file access and tool execution (GPT-
|
|
38
|
-
aliases: [
|
|
39
|
-
'gpt-5-codex',
|
|
40
|
-
'gpt5-codex',
|
|
41
|
-
'gpt-5.2-codex',
|
|
42
|
-
'gpt-5.3-codex',
|
|
43
|
-
'gpt5.3-codex',
|
|
44
|
-
'gpt-5.5',
|
|
45
|
-
'gpt5.5',
|
|
46
|
-
'gpt-5.6-codex',
|
|
47
|
-
'gpt5.6-codex',
|
|
48
|
-
],
|
|
87
|
+
'OpenAI Codex agentic coding assistant with local file access and tool execution (GPT-6 Astra by default; pick another backend with codex:<model> or CODEX_MODEL)',
|
|
88
|
+
aliases: [],
|
|
49
89
|
},
|
|
50
90
|
};
|
|
51
91
|
|
|
@@ -195,6 +235,57 @@ function extractPromptText(input) {
|
|
|
195
235
|
.join('\n\n');
|
|
196
236
|
}
|
|
197
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Resolve a backend slug or alias (case-insensitive) to its catalog slug.
|
|
240
|
+
* @param {string} name
|
|
241
|
+
* @returns {string|null}
|
|
242
|
+
*/
|
|
243
|
+
function findBackendSlug(name) {
|
|
244
|
+
const lower = String(name || '').trim().toLowerCase();
|
|
245
|
+
if (!lower) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
if (CODEX_BACKEND_MODELS[lower]) {
|
|
249
|
+
return lower;
|
|
250
|
+
}
|
|
251
|
+
return (
|
|
252
|
+
Object.keys(CODEX_BACKEND_MODELS).find((slug) =>
|
|
253
|
+
CODEX_BACKEND_MODELS[slug].aliases.includes(lower),
|
|
254
|
+
) || null
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Catalog entry for a backend model, or null when the slug is not catalogued.
|
|
260
|
+
* @param {string} name - Backend slug or alias
|
|
261
|
+
* @returns {{ slug: string, aliases: string[], contextWindow: number, supportedEfforts: string[] }|null}
|
|
262
|
+
*/
|
|
263
|
+
export function getBackendModelConfig(name) {
|
|
264
|
+
const slug = findBackendSlug(name);
|
|
265
|
+
return slug ? { slug, ...CODEX_BACKEND_MODELS[slug] } : null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Resolve the requested model spec to the backend slug passed to the CLI.
|
|
270
|
+
*
|
|
271
|
+
* `codex` uses CODEX_MODEL (default gpt-6-astra); `codex:<model>` names a
|
|
272
|
+
* backend directly, by slug or alias. Unknown names pass through verbatim so a
|
|
273
|
+
* newly released model works before it is catalogued here — the CLI rejects
|
|
274
|
+
* anything the backend does not know.
|
|
275
|
+
*
|
|
276
|
+
* @param {string} spec - Requested model, e.g. 'codex' or 'codex:sol'
|
|
277
|
+
* @param {Object} [config] - Loaded configuration
|
|
278
|
+
* @returns {string} Backend slug for the SDK's `model` option
|
|
279
|
+
*/
|
|
280
|
+
export function resolveBackendModel(spec, config) {
|
|
281
|
+
const raw = String(spec || '').trim();
|
|
282
|
+
const requested = raw.toLowerCase().startsWith('codex:')
|
|
283
|
+
? raw.slice('codex:'.length).trim()
|
|
284
|
+
: '';
|
|
285
|
+
const name = requested || config?.providers?.codexmodel || DEFAULT_BACKEND_MODEL;
|
|
286
|
+
return findBackendSlug(name) || name;
|
|
287
|
+
}
|
|
288
|
+
|
|
198
289
|
/**
|
|
199
290
|
* Get thread ID from continuation metadata.
|
|
200
291
|
* Codex thread IDs are stored per call-plan in `providerThreads`, keyed by a
|
|
@@ -216,12 +307,6 @@ async function getThreadIdFromContinuation(
|
|
|
216
307
|
}
|
|
217
308
|
}
|
|
218
309
|
|
|
219
|
-
/**
|
|
220
|
-
* Every Codex reasoning tier, weakest to strongest. Used to clamp a requested
|
|
221
|
-
* tier onto the set a given model actually accepts.
|
|
222
|
-
*/
|
|
223
|
-
const EFFORT_LADDER = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
224
|
-
|
|
225
310
|
/**
|
|
226
311
|
* Tool-level reasoning_effort values translated to their Codex equivalent.
|
|
227
312
|
* Tool enum: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'max'
|
|
@@ -232,7 +317,7 @@ const EFFORT_ALIASES = {
|
|
|
232
317
|
low: 'low',
|
|
233
318
|
medium: 'medium',
|
|
234
319
|
high: 'high',
|
|
235
|
-
max: '
|
|
320
|
+
max: 'max',
|
|
236
321
|
};
|
|
237
322
|
|
|
238
323
|
/**
|
|
@@ -403,8 +488,9 @@ export const codexProvider = {
|
|
|
403
488
|
const approvalPolicy = config.providers?.codexapprovalpolicy || 'never';
|
|
404
489
|
|
|
405
490
|
// Create or resume thread
|
|
491
|
+
const backendModel = resolveBackendModel(model, config);
|
|
406
492
|
const threadOptions = {
|
|
407
|
-
model:
|
|
493
|
+
model: backendModel,
|
|
408
494
|
workingDirectory,
|
|
409
495
|
sandboxMode,
|
|
410
496
|
skipGitRepoCheck,
|
|
@@ -413,13 +499,12 @@ export const codexProvider = {
|
|
|
413
499
|
|
|
414
500
|
if (reasoning_effort) {
|
|
415
501
|
const supportedEfforts =
|
|
416
|
-
|
|
417
|
-
SUPPORTED_MODELS.codex.supportedEfforts;
|
|
502
|
+
getBackendModelConfig(backendModel)?.supportedEfforts || EFFORT_LADDER;
|
|
418
503
|
const mappedEffort = mapReasoningEffort(reasoning_effort, supportedEfforts);
|
|
419
504
|
threadOptions.modelReasoningEffort = mappedEffort;
|
|
420
505
|
if (mappedEffort !== EFFORT_ALIASES[reasoning_effort]) {
|
|
421
506
|
debugLog(
|
|
422
|
-
`[Codex] reasoning_effort "${reasoning_effort}" not supported by ${
|
|
507
|
+
`[Codex] reasoning_effort "${reasoning_effort}" not supported by ${backendModel} — using "${mappedEffort}"`,
|
|
423
508
|
);
|
|
424
509
|
}
|
|
425
510
|
}
|
|
@@ -470,6 +555,7 @@ export const codexProvider = {
|
|
|
470
555
|
metadata: {
|
|
471
556
|
provider: 'codex',
|
|
472
557
|
model,
|
|
558
|
+
backendModel,
|
|
473
559
|
threadId: threadIdFromStream || thread.id,
|
|
474
560
|
usage: usage
|
|
475
561
|
? {
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
*
|
|
21
21
|
* The provider registry key remains 'gemini-cli' and the user-facing alias
|
|
22
22
|
* remains 'gemini' for routing/normalization stability. Only three user-facing
|
|
23
|
-
* model names are exposed: gemini (= gemini:
|
|
23
|
+
* model names are exposed: gemini (= gemini:flash), gemini:flash, gemini:pro.
|
|
24
|
+
* Flash is the default: Gemini 3.8 Flash is the current-generation model agy
|
|
25
|
+
* lists first, while 3.1 Pro remains the only Pro tier Antigravity offers.
|
|
24
26
|
*/
|
|
25
27
|
|
|
26
28
|
import { existsSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
@@ -57,7 +59,7 @@ const PTY_COLS = 1000;
|
|
|
57
59
|
const SUPPORTED_MODELS = {
|
|
58
60
|
gemini: {
|
|
59
61
|
modelName: 'gemini',
|
|
60
|
-
friendlyName: 'Gemini 3.
|
|
62
|
+
friendlyName: 'Gemini 3.8 Flash (via Antigravity CLI)',
|
|
61
63
|
contextWindow: 1048576,
|
|
62
64
|
maxOutputTokens: 65536,
|
|
63
65
|
supportsStreaming: true,
|
|
@@ -66,14 +68,14 @@ const SUPPORTED_MODELS = {
|
|
|
66
68
|
supportsThinking: true,
|
|
67
69
|
timeout: DEFAULT_TIMEOUT_MS,
|
|
68
70
|
description:
|
|
69
|
-
'Gemini 3.
|
|
71
|
+
'Gemini 3.8 Flash via Antigravity CLI (agy) - requires Antigravity Google OAuth login',
|
|
70
72
|
aliases: ['gemini-cli'],
|
|
71
73
|
// agy display-name base; reasoning_effort selects the parenthesized variant
|
|
72
|
-
agyModelBase: 'Gemini 3.
|
|
74
|
+
agyModelBase: 'Gemini 3.8 Flash',
|
|
73
75
|
},
|
|
74
|
-
'gemini:
|
|
75
|
-
modelName: 'gemini:
|
|
76
|
-
friendlyName: 'Gemini 3.
|
|
76
|
+
'gemini:flash': {
|
|
77
|
+
modelName: 'gemini:flash',
|
|
78
|
+
friendlyName: 'Gemini 3.8 Flash (via Antigravity CLI)',
|
|
77
79
|
contextWindow: 1048576,
|
|
78
80
|
maxOutputTokens: 65536,
|
|
79
81
|
supportsStreaming: true,
|
|
@@ -82,13 +84,13 @@ const SUPPORTED_MODELS = {
|
|
|
82
84
|
supportsThinking: true,
|
|
83
85
|
timeout: DEFAULT_TIMEOUT_MS,
|
|
84
86
|
description:
|
|
85
|
-
'Gemini 3.
|
|
86
|
-
aliases: [],
|
|
87
|
-
agyModelBase: 'Gemini 3.
|
|
87
|
+
'Gemini 3.8 Flash via Antigravity CLI (agy) - explicit alias of `gemini`',
|
|
88
|
+
aliases: ['flash'],
|
|
89
|
+
agyModelBase: 'Gemini 3.8 Flash',
|
|
88
90
|
},
|
|
89
|
-
'gemini:
|
|
90
|
-
modelName: 'gemini:
|
|
91
|
-
friendlyName: 'Gemini 3.
|
|
91
|
+
'gemini:pro': {
|
|
92
|
+
modelName: 'gemini:pro',
|
|
93
|
+
friendlyName: 'Gemini 3.1 Pro (via Antigravity CLI)',
|
|
92
94
|
contextWindow: 1048576,
|
|
93
95
|
maxOutputTokens: 65536,
|
|
94
96
|
supportsStreaming: true,
|
|
@@ -97,9 +99,9 @@ const SUPPORTED_MODELS = {
|
|
|
97
99
|
supportsThinking: true,
|
|
98
100
|
timeout: DEFAULT_TIMEOUT_MS,
|
|
99
101
|
description:
|
|
100
|
-
'Gemini 3.
|
|
101
|
-
aliases: ['
|
|
102
|
-
agyModelBase: 'Gemini 3.
|
|
102
|
+
'Gemini 3.1 Pro via Antigravity CLI (agy) - requires Antigravity Google OAuth login',
|
|
103
|
+
aliases: ['pro'],
|
|
104
|
+
agyModelBase: 'Gemini 3.1 Pro',
|
|
103
105
|
},
|
|
104
106
|
};
|
|
105
107
|
|
|
@@ -175,7 +177,7 @@ export function findAgyBinary() {
|
|
|
175
177
|
/**
|
|
176
178
|
* Map a reasoning_effort value to the agy parenthesized variant suffix.
|
|
177
179
|
* Flash supports Low/Medium/High; Pro supports Low/High (no Medium).
|
|
178
|
-
* @param {string} base - agy model base ('Gemini 3.
|
|
180
|
+
* @param {string} base - agy model base ('Gemini 3.8 Flash' / 'Gemini 3.1 Pro')
|
|
179
181
|
* @param {string} [reasoningEffort]
|
|
180
182
|
* @returns {string} e.g. '(Low)', '(Medium)', '(High)'
|
|
181
183
|
*/
|
|
@@ -207,7 +209,7 @@ function effortSuffix(base, reasoningEffort) {
|
|
|
207
209
|
* verbatim so power users aren't blocked.
|
|
208
210
|
* @param {string} model - e.g. 'gemini', 'gemini:flash', or a full agy name
|
|
209
211
|
* @param {string} [reasoningEffort]
|
|
210
|
-
* @returns {string} agy --model value, e.g. 'Gemini 3.
|
|
212
|
+
* @returns {string} agy --model value, e.g. 'Gemini 3.8 Flash (High)'
|
|
211
213
|
*/
|
|
212
214
|
export function resolveAgyModel(model, reasoningEffort) {
|
|
213
215
|
const raw = typeof model === 'string' ? model.trim() : '';
|
|
@@ -230,11 +232,11 @@ export function resolveAgyModel(model, reasoningEffort) {
|
|
|
230
232
|
!nameLower ||
|
|
231
233
|
nameLower === 'gemini' ||
|
|
232
234
|
nameLower === 'gemini-cli' ||
|
|
233
|
-
nameLower === '
|
|
235
|
+
nameLower === 'flash'
|
|
234
236
|
) {
|
|
235
237
|
base = SUPPORTED_MODELS.gemini.agyModelBase;
|
|
236
|
-
} else if (nameLower === '
|
|
237
|
-
base = SUPPORTED_MODELS['gemini:
|
|
238
|
+
} else if (nameLower === 'pro') {
|
|
239
|
+
base = SUPPORTED_MODELS['gemini:pro'].agyModelBase;
|
|
238
240
|
} else {
|
|
239
241
|
// Unknown suffix: pass through verbatim (power-user agy display name)
|
|
240
242
|
return raw;
|
|
@@ -762,19 +764,16 @@ export const geminiCliProvider = {
|
|
|
762
764
|
|
|
763
765
|
const name = modelName.toLowerCase().trim();
|
|
764
766
|
|
|
765
|
-
// Full agy display-name passthrough → matching
|
|
766
|
-
|
|
767
|
+
// Full agy display-name passthrough → matching tier config. Any 3.x Flash
|
|
768
|
+
// (agy also lists 3.6/3.7) shares the Flash config; any 3.x Pro the Pro one.
|
|
769
|
+
if (/gemini 3\.\d+ flash/i.test(modelName)) {
|
|
767
770
|
return SUPPORTED_MODELS['gemini:flash'];
|
|
768
771
|
}
|
|
769
|
-
if (/gemini 3
|
|
770
|
-
return SUPPORTED_MODELS.gemini;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
if (name === 'pro') {
|
|
772
|
+
if (/gemini 3\.\d+ pro/i.test(modelName)) {
|
|
774
773
|
return SUPPORTED_MODELS['gemini:pro'];
|
|
775
774
|
}
|
|
776
775
|
|
|
777
|
-
// Exact key match (gemini, gemini:
|
|
776
|
+
// Exact key match (gemini, gemini:flash, gemini:pro)
|
|
778
777
|
if (SUPPORTED_MODELS[name]) {
|
|
779
778
|
return SUPPORTED_MODELS[name];
|
|
780
779
|
}
|
package/src/providers/google.js
CHANGED
|
@@ -127,6 +127,32 @@ const SUPPORTED_MODELS = {
|
|
|
127
127
|
'3.5-flash',
|
|
128
128
|
],
|
|
129
129
|
},
|
|
130
|
+
'gemini-3.8-flash': {
|
|
131
|
+
modelName: 'gemini-3.8-flash',
|
|
132
|
+
friendlyName: 'Gemini (Flash 3.8)',
|
|
133
|
+
contextWindow: 1048576, // 1M tokens
|
|
134
|
+
maxOutputTokens: 65536,
|
|
135
|
+
supportsStreaming: true,
|
|
136
|
+
supportsImages: true,
|
|
137
|
+
supportsThinking: true,
|
|
138
|
+
supportsWebSearch: true,
|
|
139
|
+
thinkingMode: 'level',
|
|
140
|
+
// 3.8 Flash rejects thinkingLevel "minimal" outright (API error), unlike 3.5.
|
|
141
|
+
thinkingLevels: ['low', 'medium', 'high'],
|
|
142
|
+
timeout: 900000,
|
|
143
|
+
description:
|
|
144
|
+
'Gemini 3.8 Flash - Current-generation Flash with stronger long-horizon agentic performance (1M context)',
|
|
145
|
+
aliases: [
|
|
146
|
+
'gemini-3.8',
|
|
147
|
+
'gemini3.8',
|
|
148
|
+
'gemini-3.8-flash-latest',
|
|
149
|
+
'flash-3.8',
|
|
150
|
+
'flash3.8',
|
|
151
|
+
'gemini-flash-3.8',
|
|
152
|
+
'gemini flash 3.8',
|
|
153
|
+
'3.8-flash',
|
|
154
|
+
],
|
|
155
|
+
},
|
|
130
156
|
};
|
|
131
157
|
|
|
132
158
|
// Thinking mode budget percentages
|
|
@@ -514,10 +540,17 @@ export const googleProvider = {
|
|
|
514
540
|
};
|
|
515
541
|
thinkingLevel = levelMap[reasoning_effort] || 'high';
|
|
516
542
|
if (!modelConfig.thinkingLevels.includes(thinkingLevel)) {
|
|
543
|
+
// Clamp to the nearest supported level: a request below the
|
|
544
|
+
// model's floor (e.g. minimal on 3.8 Flash) takes the lowest
|
|
545
|
+
// level, anything else the highest.
|
|
546
|
+
const rank = ['minimal', 'low', 'medium', 'high'];
|
|
547
|
+
const [lowest] = modelConfig.thinkingLevels;
|
|
517
548
|
thinkingLevel =
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
549
|
+
rank.indexOf(thinkingLevel) < rank.indexOf(lowest)
|
|
550
|
+
? lowest
|
|
551
|
+
: modelConfig.thinkingLevels[
|
|
552
|
+
modelConfig.thinkingLevels.length - 1
|
|
553
|
+
];
|
|
521
554
|
}
|
|
522
555
|
} else {
|
|
523
556
|
// Binary levels only (Gemini 3.0 Pro: low/high)
|
|
@@ -138,9 +138,10 @@ function classifyModelSpec(spec, providers) {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// Other explicit namespaces pass the spec through unchanged; the target
|
|
141
|
-
// provider strips its own prefix (preserves current copilot/claude/gemini-cli
|
|
141
|
+
// provider strips its own prefix (preserves current codex/copilot/claude/gemini-cli
|
|
142
142
|
// behavior).
|
|
143
143
|
if (
|
|
144
|
+
lower.startsWith('codex:') ||
|
|
144
145
|
lower.startsWith('copilot:') ||
|
|
145
146
|
lower.startsWith('claude:') ||
|
|
146
147
|
lower.startsWith('gemini:')
|
|
@@ -308,8 +309,9 @@ export function mapModelToProvider(model, providers) {
|
|
|
308
309
|
return 'openai';
|
|
309
310
|
}
|
|
310
311
|
|
|
311
|
-
// Check Codex
|
|
312
|
-
|
|
312
|
+
// Check Codex: bare `codex` or the `codex:<backend>` namespace (e.g. codex:astra,
|
|
313
|
+
// codex:gpt-5.6-sol). Bare "gpt-*" names never route here — they are OpenAI API models.
|
|
314
|
+
if (modelLower === 'codex' || modelLower.startsWith('codex:')) {
|
|
313
315
|
return 'codex';
|
|
314
316
|
}
|
|
315
317
|
|