Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/architecture/code-organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Additional focused owners:
| Domain | Owner and boundary | Focused tests to start with |
| --- | --- | --- |
| Claude SDK events | `electron/providers/claude-event-mapping.ts` translates SDK events using supplied tracker/plan state; `claude-sdk-runtime.ts` owns turn state and rate-limit observation side effects; `src/lib/session/provider-event-replay.ts` and `src/lib/work-graph/work-graph-reducer.ts` consume normalized events and correlate tool results with earlier tool calls | `tests/claude-sdk-runtime.test.ts`, `tests/claude-rate-limits-observation.test.ts`; inspect replay or work-graph tests when their state changes |
| Codex server requests | `electron/providers/codex-server-request-mapping.ts` maps approval/question presentation and response metadata; `codex-app-server-runtime.ts` owns filtering, pending requests, timers, auth, and responses | `tests/codex-server-request-mapping.test.ts`, `tests/codex-app-server-runtime.test.ts` |
| Codex server requests | `electron/providers/codex-server-request-mapping.ts` maps approval/question presentation and response metadata; `codex-app-server-runtime.ts` owns filtering, pending requests, timers, auth, and responses; `codex-ensure-thread.ts` starts or resumes the thread and retries once on GPT-6 Sol when GPT-6.1 Sol is unavailable | `tests/codex-server-request-mapping.test.ts`, `tests/codex-app-server-runtime.test.ts`, `tests/codex-ensure-thread.test.ts` |
| Codex turn notification ownership | `electron/providers/codex-turn-notification-gate.ts` buffers early notifications until the acknowledged turn is known; the runtime replays matching events and resolves child-thread ownership | `tests/codex-turn-notification-gate.test.ts`, `tests/codex-app-server-mcp-lifecycle.test.ts`; opt-in `tests/e2e-electron/provider-live-smoke.electron.e2e.ts` covers cancel/retry/resume |
| Codex interrupted turns | `electron/providers/codex-orphan-turn-cleanup.ts` waits for native completion before same-thread retry and quarantines unresolved threads; `codex-app-server-pending-request.ts` releases abandoned local RPC waits | `tests/codex-orphan-turn-cleanup.test.ts`, `tests/codex-app-server-pending-request.test.ts`, `tests/codex-app-server-mcp-lifecycle.test.ts`; `tests/e2e-electron/codex-interrupted-start.electron.e2e.ts` covers injected failure recovery in the built app |
| Codex settings UI | `src/components/layout/settings-dialog-codex-section.tsx` owns requests, selection, drafts, and mutations; `codex-settings/` contains the five tab views and shared presentation | `tests/e2e/codex-settings-refactor.e2e.ts` exercises the parent against a mocked provider bridge |
Expand Down
3 changes: 2 additions & 1 deletion docs/architecture/entrypoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ turn; `codex-app-server-pending-request.ts` owns local RPC wait cancellation.
For Codex settings snapshots or the model catalog, start at
`electron/providers/codex-app-server-snapshot.ts` and follow its facade in
`electron/providers/codex-app-server-runtime.ts`. Turn execution remains in the
runtime adapter.
runtime adapter. Thread start and the GPT-6.1 Sol fallback live in
`electron/providers/codex-ensure-thread.ts`.

### Sending a conversation turn

Expand Down
52 changes: 31 additions & 21 deletions docs/providers/provider-runtimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,8 @@ before building the call.

| | Claude | Codex | Cursor | Kiro |
| -------------------------- | -------------------------------------------- | ------------------------------------------ | ---------------------------------------- | ---------------------------------------- |
| orchestrating primaries | Fable 5.1, Opus 5.5 (+1M), Sonnet 5.5 (+1M) | GPT-6 Astra, GPT-5.6 Sol, GPT-5.6 Terra | runtime ACP catalog | runtime model catalog |
| worker models | Sonnet 5.5 (+1M), Haiku 4.5, Opus 5.5, Fable 5.1 | Terra, Sol | runtime ACP catalog | runtime model catalog |
| orchestrating primaries | Fable 5.1, Opus 5.5 (+1M), Sonnet 5.5 (+1M) | GPT-6 Astra, GPT-6.1 Sol, GPT-6 Sol, GPT-5.6 Terra | runtime ACP catalog | runtime model catalog |
| worker models | Sonnet 5.5 (+1M), Haiku 4.5, Opus 5.5, Fable 5.1 | GPT-6.1 Sol, GPT-6 Sol, Terra | runtime ACP catalog | runtime model catalog |
| execution adapter | native named agent | native spawned agent | task-scoped ACP role session | task-scoped ACP role session |
| worker model pinning | `AgentDefinition.model` | `agents.default_subagent_model` | ACP config option | ACP model selection |
| worker effort pinning | `AgentDefinition.effort` | `agents.default_subagent_reasoning_effort` | encoded in the selected model variant | ACP process `--effort` |
Expand Down Expand Up @@ -1004,7 +1004,7 @@ Compaction checkpoint UI support:

## Codex runtime

Codex turns are handled in `electron/providers/codex-app-server-runtime.ts`.
Codex turns are handled in `electron/providers/codex-app-server-runtime.ts`. Thread start and resume, including the one retry from GPT-6.1 Sol onto GPT-6 Sol, live in `electron/providers/codex-ensure-thread.ts`.

High-level flow:

Expand Down Expand Up @@ -1226,7 +1226,7 @@ When a task switches from one Codex model to another, Stave does not attempt to

- Codex App Server transport: local `codex app-server` from Codex CLI `0.145.0`
- Current schema verification baseline: `0.145.0` (verified July 31, 2026)
- Current Stave-supported Codex model IDs: `gpt-6-astra`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5` (default: `gpt-5.6-sol`; `gpt-6-astra` is the frontier tier)
- Current Stave-supported Codex model IDs: `gpt-6-astra`, `gpt-6.1-sol`, `gpt-5.6-terra`, `gpt-6-luna` (default: `gpt-6.1-sol`; `gpt-6-sol` is the fallback when 6.1 is unavailable; `gpt-6-astra` is the frontier tier)

### Default-effort ladder

Expand All @@ -1236,7 +1236,7 @@ model; smaller models are not handed a deeper budget to compensate:
| Rung | Claude | Codex | Default effort |
| -------- | -------------- | ------------- | -------------- |
| frontier | Fable 5.1 | GPT-6 Astra | `medium` |
| flagship | Opus 5.5 (+1M) | GPT-6 Sol | Opus `medium`; Sol `high` |
| flagship | Opus 5.5 (+1M) | GPT-6.1 Sol | Opus `medium`; Sol 6.1 `high` |
| balanced | Sonnet 5.5 (+1M) | GPT-5.6 Terra | Sonnet `high`; Terra `xhigh` |
| light | — | GPT-6 Luna | `xhigh` |

Expand All @@ -1249,12 +1249,14 @@ recall collapses (MRCR 8-needle 41%) whatever the effort. Raising or lowering
the tier stays a deliberate per-turn choice.

Sonnet 5.5's composer default is `high`. Its list price is half of Opus 5.5,
so ordinary Auto routes use the balanced rung at `high`. GPT-6 Sol lists at
the same price and its composer default is `high` too. Terra sits one step
so ordinary Auto routes use the balanced rung at `high`. GPT-6.1 Sol lists at
the same price and keeps the same composer default as GPT-6 Sol, `high`.
GPT-6 Sol remains available as the fallback and keeps `high`. Terra sits one step
higher, at `xhigh`. Luna's composer default is `xhigh`, and Auto's bounded
route uses that same effort. A turn sends the effort stored in Stave. Sol,
Terra, and Luna keep those Stave defaults after the App Server catalog is
fetched. Other Codex models still follow that catalog's
route uses that same effort. A turn sends the effort stored in Stave. GPT-6.1
Sol, GPT-6 Sol, Terra, and Luna keep those Stave defaults after the App Server
catalog is fetched.
Other Codex models still follow that catalog's
`defaultReasoningEffort` when the stored effort is still the previous
default. `xhigh` and `max` stay off Sonnet and Sol. High complexity and
uncertain intent stay on Opus 5.5 at `high` effort. Safety-critical work stays on Fable. Cost-saver still steps that
Expand All @@ -1267,8 +1269,9 @@ it. Legacy `gpt-5.5` keeps the `xhigh` cap it was verified at.
Two knock-on effects worth knowing:

- The Advisor deadline is tiered by effort (`resolveAdvisorTimeoutMs`). An
unpinned advisor uses the model default, so Opus 5.5 lands on `medium` and
Sonnet 5.5 and GPT-6 Sol land on `high`, and Terra lands on `xhigh`.
unpinned advisor uses the model default, so Opus 5.5 lands on `medium`,
GPT-6.1 Sol, GPT-6 Sol, and Sonnet 5.5 land on `high`, and Terra lands on
`xhigh`.
- Fresh-install `claudeEffort` / `codexReasoningEffort` seeds track the default
model's rung. Existing users are carried over by the one-time settings
migration in `src/lib/providers/settings-model-migration.ts`, which moves a
Expand All @@ -1280,7 +1283,8 @@ Two knock-on effects worth knowing:
unchanged, because `high` is the default for both. Another step moves GPT-6
Sol from `medium` to `high` when the stored effort is still that old default.
A further step moves Luna from `medium` to `xhigh` and Terra from `high` to
`xhigh` on the same rule.
`xhigh` on the same rule. The latest step moves a selected GPT-6 Sol to
GPT-6.1 Sol and leaves the stored effort unchanged.

Stave requires a user-installed Codex CLI. Users must have Codex CLI available in their PATH or configured via `runtimeOptions.codexBinaryPath` / `STAVE_CODEX_CLI_PATH`. A user-configured binary path still takes precedence over auto-discovery. Stave does not currently enforce a semantic-version floor, so controls for newly adopted features must be capability-gated for older executables.

Expand Down Expand Up @@ -1498,11 +1502,14 @@ the case the floor above still allows.

## September 2026 model catalog

The primary Codex catalog includes GPT-6 Astra, GPT-6 Sol, GPT-5.6 Terra
(the balanced tier), and GPT-6 Luna. New tasks default to GPT-6 Sol;
utility inference and light-tier routing use GPT-6 Luna. Codex Sol supports
Low through Ultra, while Luna caps at Max. Sol starts at High. Luna and Terra
start at Extra High. See the [Codex model guide](https://learn.chatgpt.com/docs/models).
The primary Codex catalog includes GPT-6 Astra, GPT-6.1 Sol, GPT-5.6 Terra
(the balanced tier), and GPT-6 Luna. New tasks default to GPT-6.1 Sol.
When that model is unavailable, Stave starts the turn on GPT-6 Sol instead.
Utility inference and light-tier routing use GPT-6 Luna. Codex Sol supports
Low through Ultra, while Luna caps at Max. GPT-6.1 Sol and GPT-6 Sol both
start at High. Luna and Terra start at Extra High. GPT-6.1 Sol
was present in the Codex CLI 0.159.1 bundled catalog; no minimum client
version is assigned. See the [Codex model guide](https://learn.chatgpt.com/docs/models).

Claude defaults to `claude-opus-5-5` at Medium effort. The existing 1M variant
and Opus 4.8 overload fallback remain available. Opus 5.5 rejects disabled or
Expand All @@ -1524,7 +1531,8 @@ shortcut/preset seeds. A selected Sonnet 5 id, including one stored on a
shortcut or task preset, moves to Sonnet 5.5. That step does not rewrite
effort. A selected GPT-6 Sol whose effort is still `medium` moves to `high`.
A selected Luna whose effort is still `medium` moves to `xhigh`, and a selected
Terra whose effort is still `high` moves to `xhigh`.
Terra whose effort is still `high` moves to `xhigh`. A selected GPT-6 Sol then
moves to GPT-6.1 Sol, and that step leaves the stored effort unchanged.
Other selected models, tuned efforts, and historical turns keep their saved
values. Cursor and
Kiro continue to use their own runtime-advertised catalogs. Provider account
Expand All @@ -1541,13 +1549,15 @@ changes are also surfaced when the CLI omits a fallback event; in that case,
the cause is explicitly unknown. The response model label follows the actual
model. This fallback observation is specific to Claude.

Codex also surfaces model changes from `thread/start` and `thread/resume`
When Codex reports that GPT-6.1 Sol is unavailable, Stave retries the thread
once on GPT-6 Sol and records that substitution. Codex also surfaces model
changes from `thread/start` and `thread/resume`
responses and `model/rerouted` notifications, updating the response model label.
Notifications are scoped to the active thread and turn. Recognized reroute reasons
are shown without treating policy routing as a version failure. Unsupported-model
and outdated-client errors retain the provider's message (including any minimum
version) and add installation-specific update guidance. No unverified minimum
version is assigned to GPT-6 Sol or Luna. See the [CLI installation guide](https://learn.chatgpt.com/docs/codex/cli).
version is assigned to GPT-6.1 Sol, GPT-6 Sol, or Luna. See the [CLI installation guide](https://learn.chatgpt.com/docs/codex/cli).

Model selection remains non-blocking when runtime support is unknown. Codex
picker descriptions distinguish entries advertised by the current runtime from
Expand Down
21 changes: 16 additions & 5 deletions electron/providers/codex-app-server-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,26 @@ export function toErrorMessage(error: unknown) {
return error instanceof Error ? error.message : String(error);
}

function matchesUnavailableModel(message: string) {
return (
/(?:codex|client|cli).*(?:version.*(?:too old|not supported)|outdated)/i.test(message)
|| /requires? (?:codex|client|cli) (?:version )?\d/i.test(message)
|| /model.*(?:not supported|not available|does not exist|unsupported)/i.test(message)
);
}

export function isCodexModelUnavailableError(message: string) {
return (
matchesUnavailableModel(message) ||
matchesUnavailableModel(formatCodexAppServerErrorMessage(message))
);
}

export function toCodexUserFacingErrorMessage(args: { message: string }) {
const message = formatCodexAppServerErrorMessage(args.message);
const lower = message.toLowerCase();
const rawLower = args.message.toLowerCase();
if (
/(?:codex|client|cli).*(?:version.*(?:too old|not supported)|outdated)/i.test(message)
|| /requires? (?:codex|client|cli) (?:version )?\d/i.test(message)
|| /model.*(?:not supported|not available|does not exist|unsupported)/i.test(message)
) {
if (isCodexModelUnavailableError(message)) {
return `${message}\n${CODEX_MODEL_UPDATE_GUIDANCE} Model access can also depend on your account.`;
}
if (
Expand Down
Loading
Loading