Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1ba5c60
docs: design native JEV auto routing
Sep 21, 2026
c4cd3cc
docs: plan native JEV auto routing
Sep 21, 2026
511f59a
feat: add JEV combo decision contract
Sep 21, 2026
cd8d16e
feat: add TypeSafe JEV provider setup
Sep 21, 2026
ec8b6a2
feat: route jev-auto through combo runtime
Sep 21, 2026
9af7a9d
feat(gui): add JEV Auto setup flow
Sep 21, 2026
ab896b9
fix: harden JEV auto routing
Sep 21, 2026
71aab27
fix: align JEV provider registry contracts
Sep 21, 2026
0a148c3
fix: address JEV review findings
Sep 21, 2026
0307590
fix: avoid redundant JEV task scan
Sep 21, 2026
2963460
chore: merge upstream dev
Sep 21, 2026
415a0ca
fix: strip protected envelopes from JEV context
Sep 21, 2026
a87af4e
feat: add per-target JEV effort controls
Sep 22, 2026
7ce2af7
Merge remote-tracking branch 'upstream/dev' into feat/jev-auto-routing
Sep 22, 2026
9ee4f2c
fix: address final JEV review feedback
Sep 22, 2026
90a7666
feat: add JEV routing statistics
Sep 22, 2026
d05dfaf
fix: harden JEV statistics aggregation
Sep 22, 2026
fcbe926
chore: merge upstream dev into JEV routing
kingkej Sep 22, 2026
c7a723d
chore: merge upstream dev into JEV routing
kingkej Sep 22, 2026
5154ccf
chore: merge upstream dev into JEV routing
Sep 22, 2026
5e8ff89
chore: merge upstream dev into JEV routing
Sep 23, 2026
80cb53d
Merge remote-tracking branch 'upstream/dev' into feat/jev-auto-routing
Sep 23, 2026
02fb559
Merge remote-tracking branch 'origin/dev' into feat/jev-auto-routing
lidge-jun Sep 25, 2026
aabd6a7
docs(jev): record TypeSafe retention terms and sync preset counts
lidge-jun Sep 25, 2026
d540cff
test(gui): expect dev's imageInput default in the JEV PUT body
lidge-jun Sep 25, 2026
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ocx init

`ocx init` vous accompagne dans les étapes suivantes :

1. **Choix d’un fournisseur** — sélectionnez l’un des 96 préréglages intégrés au registre, ou `custom` pour saisir une
1. **Choix d’un fournisseur** — sélectionnez l’un des 97 préréglages intégrés au registre, ou `custom` pour saisir une
URL de base et un adaptateur.
2. **Clé API** — collez une clé ou référencez une variable d’environnement telle que `${ANTHROPIC_API_KEY}`.
3. **Modèle par défaut** — pour les fournisseurs clés, locaux et personnalisés, acceptez le préréglage ou saisissez un identifiant de modèle.
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/fr/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ existante n'est pas concernée.

## 3. Catalogue des clés API

opencodex fournit 96 préréglages intégrés : 80 à clé, 12 OAuth, trois locaux et un préréglage par défaut de
opencodex fournit 97 préréglages intégrés : 81 à clé, 12 OAuth, trois locaux et un préréglage par défaut de
transfert ChatGPT. Dans le tableau de bord, le sélecteur **Ajouter un fournisseur** ouvre le tableau de bord du
fournisseur à clé, valide la clé et l'enregistre ; la validation dépend du fournisseur. Parmi les entrées notables :

Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ocx init

`ocx init` walks you through:

1. **Pick a provider** — choose one of the 96 built-in registry presets or `custom` to type a base
1. **Pick a provider** — choose one of the 97 built-in registry presets or `custom` to type a base
URL and adapter.
2. **API key** — paste a key, or reference an environment variable like `${ANTHROPIC_API_KEY}`.
3. **Default model** — for key, local, and custom providers, accept the preset or enter a model id.
Expand Down
88 changes: 85 additions & 3 deletions docs-site/src/content/docs/guides/combos.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,86 @@ order. Weights and `stickyLimit` do not affect this strategy.

This ranking and provider exclusion before dispatch require fresh model-inference limits that apply to the current single API key as a whole. OAuth/current-account summaries, caller-forward routes, multiple keys, and snapshots with changed credentials or destinations are display-only for this early decision. The same applies when `Authorization`, `x-api-key`, or `x-goog-api-key` headers override credentials; search-only and MCP-only windows are excluded. If no eligible target has an applicable reset, configuration order wins. Account selection and retries still enforce their normal limits.

### JEV: decision-guided first pick

`jev` asks [TypeSafe JEV](https://console.typesafe.ai) to choose the first eligible target and a
compatible reasoning effort for the current request. It is opt-in: adding the TypeSafe credential
does not change existing models, aliases, defaults, or Combo behavior. A JEV-backed model appears
only after you create a Combo whose strategy is `jev`.

The quickest setup is:

1. Open **Providers**, add **TypeSafe JEV**, enter the TypeSafe API key, and test the connection.
2. From that provider's Overview, choose **Create JEV Auto**. You can also use the same action under
**Models → Combos**.
3. Review the prefilled Astra → Sol → Luna targets. Add, remove, reorder, or replace them before
creating the Combo. The first currently eligible row is marked as the fail-open target, and each
known reasoning ladder is shown beside its row.

The template creates id and alias `jev-auto`, uses adaptive reasoning capability, and remains an
ordinary editable Combo. It does not become the default model. Its targets are the complete
allowlist: JEV can never select a provider/model pair outside that list, and the original target
models remain available in their normal picker groups.

For headless setup, store the key explicitly or reference the TypeSafe environment variable:

```bash
ocx provider add jev --api-key "${TYPESAFE_API_KEY}"
```

When the provider has no saved key, the decision client also accepts `TYPESAFE_API_KEY` directly and
the standard provider-derived alias `JEV_API_KEY` printed by `ocx provider add`.

```json
{
"providers": {
"jev": {
"adapter": "jev-decision",
"baseUrl": "https://api.typesafe.ai/v1/systemone",
"authMode": "key",
"apiKey": "${TYPESAFE_API_KEY}",
"liveModels": false
}
},
"combos": {
"jev-auto": {
"alias": "jev-auto",
"strategy": "jev",
"reasoningEffortMode": "adaptive",
"targets": [
{ "provider": "openai", "model": "gpt-6-astra" },
{ "provider": "openai", "model": "gpt-5.6-sol" },
{ "provider": "openai", "model": "gpt-5.6-luna" }
]
}
}
}
```

OpenCodex sends one bounded decision request to the fixed
`https://api.typesafe.ai/v1/systemone` endpoint with model `jev-latest`. Only currently eligible
configured targets are offered. JEV chooses the target and effort together; the effort is still
constrained by that target's advertised ladder. JEV is not asked again if the selected target has a
retryable failure—the existing Combo cooldown and fallback loop continues through the remaining
configured targets.

The decision boundary fails open when the key is missing, no safe task/tool/image decision state is
available, the four-second decision deadline expires, the service redirects or returns an error, or
the response is malformed or selects an unlisted choice. In those cases OpenCodex uses the first
currently eligible target, preferring `medium` when that target supports it. Caller cancellation is
different: it cancels the decision and the model request instead of dispatching the fail-open target.

The decision state is deliberately bounded: up to 500 characters of the current user task, a
240-character previous-assistant tail, a 520-character latest-tool-output tail, the tool name, and
boolean image/tool signals may be sent to TypeSafe. It excludes the JEV credential, request headers,
raw image bytes, tool arguments, encrypted reasoning, and full conversation history. Do not select
`jev-auto` for content you do not want TypeSafe to process. Recognized OpenCodex machine-context
envelopes are removed from all three text samples, but ordinary assistant and tool-output text is
not a secret scanner and may still contain sensitive content. Logs contain only the selected
target/effort, a coarse decision gate, latency, optional confidence/probability, and numeric usage.
Automated tests use mocked TypeSafe responses plus a no-key fail-open smoke; a live TypeSafe decision
requires an operator-supplied key and is not run implicitly.

## What happens when a target fails

Combo failures are divided into **hop** failures and **terminal** failures.
Expand Down Expand Up @@ -351,7 +431,9 @@ task workflow.
### Dashboard

Open the local dashboard and choose **Models → Combos**. The workspace creates, edits, renames, and removes
combos, and its target picker excludes disabled models and nested combos.
combos, and its target picker excludes disabled models, nested combos, and the credential-only JEV
provider. **Create JEV Auto** opens the same Combo editor with an editable decision target template;
an existing `jev-auto` id or alias is reported instead of creating a duplicate.

Each target also shows a live quota badge: **Available**, **Out of quota**, or **Quota unknown**. The editor blocks Save and Create for quota only when every usable target has a current server-confirmed exhausted inference limit for its configured credential. Display-only account, model, search and MCP quota, or missing or expired routing evidence, does not cause this block. The block expires at the applicable reset or freshness boundary and is rechecked when the page becomes active or visible; Refresh reloads both Combo data and quota. The dashboard
editor does not yet expose `cooldownMs` or `waitForCooldownMs`; use the configuration file or management
Expand Down Expand Up @@ -412,8 +494,8 @@ Combos are stored in the top-level `combos` object, keyed by combo id:
| Field | Required | Default | Rules |
| --- | --- | --- | --- |
| `targets` | Yes | — | Non-empty ordered array of configured `{ provider, model, weight? }` targets. Duplicate provider/model pairs are rejected. |
| `targets[].weight` | No | `1` | Integer from 1 to 10,000. Used by round-robin and random; ignored by failover, least-used, and reset-window. |
| `strategy` | No | `"failover"` | `"failover"`, `"round-robin"`, `"random"`, `"least-used"`, or `"reset-window"`. |
| `targets[].weight` | No | `1` | Integer from 1 to 10,000. Used by round-robin and random; ignored by failover, least-used, reset-window, and JEV. |
| `strategy` | No | `"failover"` | `"failover"`, `"round-robin"`, `"random"`, `"least-used"`, `"reset-window"`, or `"jev"`. JEV decides only the initial eligible target and effort; ordinary Combo fallback owns later attempts. |
| `stickyLimit` | No | `1` | Integer from 1 to 100 successful requests per round-robin selection. Applies only to round-robin. |
| `cooldownMs` | No | unset → upstream fallback (5 s for request-rate 429 codes `1302`/`1305`, otherwise 60 s) | Integer from 1 to 600000. When set, applies as the per-target cooldown whenever no usable upstream `Retry-After` or Codex reset signal exists, including request-rate 429s; when unset, uses the upstream fallback. |
| `waitForCooldownMs` | No | `0` | Integer from 0 to 600000. Maximum time to wait for the earliest eligible cooling target before returning `combo_unavailable`; abort cancels the wait. |
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ selectors, then retry. Signing in from a machine with no existing `kiro-cli` ses

## 3. API-key catalog

opencodex ships 96 built-in presets: 80 key-based, 12 OAuth, three local, and one default
opencodex ships 97 built-in presets: 81 key-based, 12 OAuth, three local, and one default
ChatGPT-forward preset. The dashboard's **Add provider** picker opens a key provider's dashboard,
validates the key, and stores it; validation is provider-specific. Notable entries:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ocx init

`ocx init` では次の手順を説明します。

1. **プロバイダーを選択してください** — 96 個の組み込みレジストリプリセットのいずれか、または `custom` を選択してベース URL とアダプターを入力します。
1. **プロバイダーを選択してください** — 97 個の組み込みレジストリプリセットのいずれか、または `custom` を選択してベース URL とアダプターを入力します。
2. **API キー** — キーを貼り付けるか、`${ANTHROPIC_API_KEY}` のような環境変数を参照します。
3. **デフォルト モデル** — キー、ローカル、カスタム プロバイダーの場合は、プリセットを受け入れるか、モデル ID を入力します。
4. **プロキシ ポート** — デフォルトは `10100` です。
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/ja/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ Kiro のログインには Kiro CLI が必要です。Unix では `curl -fsSL ht

## 3. API キーカタログ

opencodex には組み込みプリセットが 96 個含まれています。キー方式 80、OAuth 12、ローカル 3、
opencodex には組み込みプリセットが 97 個含まれています。キー方式 81、OAuth 12、ローカル 3、
デフォルト ChatGPT 転送プリセット 1 です。ダッシュボードの **Add provider** ピッカーはキー発行ページを開き、
入力したキーを検証した後保存します(検証はプロバイダー固有です)。主な項目は以下のとおりです:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ocx init

`ocx init`은 다음 과정을 안내합니다:

1. **프로바이더 선택** — 내장 레지스트리 프리셋 96개 중 하나를 고르거나 `custom`을 선택해 base URL과 adapter를 직접 입력합니다.
1. **프로바이더 선택** — 내장 레지스트리 프리셋 97개 중 하나를 고르거나 `custom`을 선택해 base URL과 adapter를 직접 입력합니다.
2. **API 키** — 키를 붙여넣거나 `${ANTHROPIC_API_KEY}` 같은 환경 변수를 참조합니다.
3. **기본 모델** — 키, 로컬, custom 프로바이더에서는 프리셋을 그대로 쓰거나 모델 ID를 직접 입력합니다.
4. **프록시 포트** — 기본값은 `10100`입니다.
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/ko/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ Kiro 로그인에는 Kiro CLI가 필요합니다. Unix에서는 `curl -fsSL http

## 3. API 키 카탈로그

opencodex에는 빌트인 프리셋이 96개 들어 있습니다. 키 방식 80개, OAuth 12개, 로컬 3개,
opencodex에는 빌트인 프리셋이 97개 들어 있습니다. 키 방식 81개, OAuth 12개, 로컬 3개,
기본 ChatGPT 포워드 프리셋 1개입니다. 대시보드의 **Add provider** 선택기는 키 발급 페이지를 열고,
입력한 키를 검증한 뒤 저장합니다(검증은 프로바이더별로 다릅니다). 주요 항목은 다음과 같습니다:

Expand Down
14 changes: 11 additions & 3 deletions docs-site/src/content/docs/reference/configuration/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ namespace, and cannot use reserved bare native families such as `gpt-*`, `o1-*`,
| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `targets` | `{ provider: string; model: string; weight?: number }[]` | required | Ordered concrete routes. `weight` is 1–10000 and defaults to `1`. |
| `strategy?` | `"failover" \| "round-robin" \| "random" \| "least-used" \| "reset-window"` | `"failover"` | Selection strategy. Target order is failover priority; weights shape round-robin and random draws; least-used follows recorded successes; reset-window follows the soonest quota reset. |
| `strategy?` | `"failover" \| "round-robin" \| "random" \| "least-used" \| "reset-window" \| "jev"` | `"failover"` | Selection strategy. Target order is failover priority; weights shape round-robin and random draws; least-used follows recorded successes; reset-window follows the soonest quota reset; JEV makes one bounded decision for the initial eligible target and effort, then uses ordinary ordered fallback. |
| `stickyLimit?` | `number` | `1` | Successful requests retained in one round-robin batch. Range 1–100. Applies only to round-robin. |
| `cooldownMs?` | `number` | unset → upstream fallback (5 s for request-rate 429 codes `1302`/`1305`, otherwise 60 s) | Range 1–600000. When set, applies whenever no usable upstream `Retry-After` or Codex reset signal exists, including request-rate 429s; when unset, uses the upstream fallback. Upstream signals take precedence and all cooldowns are capped at 10 minutes. |
| `waitForCooldownMs?` | `number` | `0` | Maximum wait for the earliest eligible cooling target on each selection attempt. Range 0–600000; an abort cancels the wait. A single-target combo with a nonzero wait holds the request up to this ceiling and retries the same target instead of failing immediately; if no target was ever dispatched the wait ends in `combo_unavailable`, otherwise the last upstream failure is returned. |
Expand Down Expand Up @@ -118,6 +118,14 @@ namespace, and cannot use reserved bare native families such as `gpt-*`, `o1-*`,
For strategy behavior, retryable failures, cooldowns, encrypted v2 task limits, and management
commands, see [Combos](/guides/combos/).

The `jev` strategy is optional and requires the canonical `jev` provider credential. That provider
is a decision service, publishes no directly routable model, and cannot be a Combo target. JEV sees
only currently eligible members of `targets`; missing, failed, or invalid decisions use the first
eligible member, while caller cancellation remains terminal. Adding the provider or Combo never
changes `defaultProvider` or hides direct model rows. See
[JEV: decision-guided first pick](/guides/combos/#jev-decision-guided-first-pick) for setup, privacy
bounds, and the one-decision-per-call contract.

## Routing policy profiles (`config.routingProfiles`)

Routing policy profiles are the Router Intelligence selection layer: an explicitly requested
Expand Down Expand Up @@ -201,8 +209,8 @@ echoed as given. The CLI dry-run cannot supply these per-candidate account field
### Combos vs policy profiles

- A **combo** is explicit target routing with a selectable strategy (ordered failover, smooth
weighted or random balancing, least-used, or reset-window): the configured strategy decides,
and retryable failures advance through the list.
weighted or random balancing, least-used, reset-window, or one bounded JEV first-pick decision):
the configured strategy decides, and retryable failures advance through the list.
- A **policy profile** is evidence-based selection among configured candidates: hard capability
requirements filter first, then deterministic scoring ranks the survivors.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ocx init

`ocx init` проведёт вас по следующим шагам:

1. **Выбор провайдера** — выберите один из 96 встроенных пресетов реестра или `custom`, чтобы
1. **Выбор провайдера** — выберите один из 97 встроенных пресетов реестра или `custom`, чтобы
ввести базовый URL и адаптер вручную.
2. **API-ключ** — вставьте ключ или сошлитесь на переменную окружения вида `${ANTHROPIC_API_KEY}`.
3. **Модель по умолчанию** — для провайдеров с ключом, локальных и `custom` примите значение из
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/ru/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ Inline JSON и лишние позиционные аргументы откло

## 3. Каталог API-ключей

opencodex поставляется с 96 встроенными пресетами: 80 на основе ключей, 12 OAuth, три локальных и
opencodex поставляется с 97 встроенными пресетами: 81 на основе ключей, 12 OAuth, три локальных и
один пресет ChatGPT-форварда по умолчанию. Селектор **Add provider** в дашборде открывает страницу
выдачи ключей провайдера, проверяет ключ и сохраняет его; проверка зависит от провайдера.
Наиболее заметные записи:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ ocx init

`ocx init` adım adım size rehberlik eder:

1. **Bir sağlayıcı seçin** — yerleşik kayıt defterindeki 96 önayardan birini
1. **Bir sağlayıcı seçin** — yerleşik kayıt defterindeki 97 önayardan birini
veya bir temel URL ile adaptör yazmak için `custom` seçeneğini belirleyin.
2. **API anahtarı** — bir anahtar yapıştırın veya `${ANTHROPIC_API_KEY}` gibi
bir ortam değişkenine başvurun.
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/tr/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ olmayan bir makineden oturum açmak bundan etkilenmez.

## 3. API anahtarı kataloğu

opencodex 96 yerleşik önayar ile birlikte gelir: 80 anahtar tabanlı, 12
opencodex 97 yerleşik önayar ile birlikte gelir: 81 anahtar tabanlı, 12
OAuth, üç yerel ve bir varsayılan ChatGPT iletme önayarı. Kontrol panelinin
**Sağlayıcı ekle** seçicisi bir anahtar sağlayıcısının kontrol panelini açar,
anahtarı doğrular ve saklar; doğrulama sağlayıcıya özgüdür. Dikkate değer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ocx init

`ocx init` 会引导你完成:

1. **选择 provider** — 从内置 registry 的 96 个预设中选择一个,或选择 `custom` 手动输入 base URL 和 adapter。
1. **选择 provider** — 从内置 registry 的 97 个预设中选择一个,或选择 `custom` 手动输入 base URL 和 adapter。
2. **API key** — 粘贴一个 key,或引用一个环境变量,例如 `${ANTHROPIC_API_KEY}`。
3. **默认模型** — 对于 key、本地和 custom provider,接受预设值或输入模型 id。
4. **代理端口** — 默认为 `10100`。
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/zh-cn/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ Kiro 登录需要 Kiro CLI:Unix 使用 `curl -fsSL https://cli.kiro.dev/instal

## 3. API 密钥目录

opencodex 内置 96 个预设:80 个密钥预设、12 个 OAuth 预设、3 个本地预设,以及 1 个默认的
opencodex 内置 97 个预设:81 个密钥预设、12 个 OAuth 预设、3 个本地预设,以及 1 个默认的
ChatGPT 转发预设。仪表盘的 **Add provider** 选择器会打开密钥提供商的控制台,验证并保存密钥。
验证因提供商而异。主要条目包括:

Expand Down
Loading
Loading