Skip to content

fix(agent): align effort schema with provider-specific capabilities - #234

Open
lucas77778 wants to merge 6 commits into
masterfrom
xuan/code-330
Open

fix(agent): align effort schema with provider-specific capabilities#234
lucas77778 wants to merge 6 commits into
masterfrom
xuan/code-330

Conversation

@lucas77778

@lucas77778 lucas77778 commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

  • extend the normalized effort schema with Codex's distinct ultra level and advertise per-model effort capabilities/defaults
  • parse Codex model/list metadata for pre-session and live catalogs, validating startup and live model/effort selections against the selected model
  • keep Codex ultra separate from Claude's ultracode, update effort filtering/fallbacks, and preserve pending picks across stale settings notifications
  • bump the wire protocol to v60 (rebased past master' simulator wire bumps)

Verification

  • pnpm test (210 files, 1,634 tests)
  • pnpm check:ci
  • git diff --check
  • verified the supportedReasoningEfforts protocol shape against @openai/codex 0.144.1

Linear: CODE-330

Co-authored-by: Chenyu Lu <chenyu@arcbox.dev>
Copilot AI review requested due to automatic review settings July 21, 2026 10:18
@linear-code

linear-code Bot commented Jul 21, 2026

Copy link
Copy Markdown
CODE-330 fix(agent): align effort schema with provider-specific capabilities

Problem

The normalized effort contract is a single global enum and the UI keeps provider effort choices in static tables. That contract no longer matches the pinned Codex 0.144.1 provider:

  • gpt-5.6-sol and gpt-5.6-terra advertise low | medium | high | xhigh | max | ultra.
  • gpt-5.6-luna advertises low | medium | high | xhigh | max.
  • The generated app-server protocol explicitly directs clients to use effort: "ultra" for proactive multi-agent behavior.
  • packages/schema/src/agent.ts:37 omits Codex ultra.
  • packages/agent-adapter/src/native/codex/adapter.ts:482 rejects max.
  • packages/ui/src/shell/agent-efforts.ts:27 assumes Codex is always low–xhigh.

A configured Codex ultra session can therefore be reflected as the model's low/medium default, and provider-supported choices are unavailable.

Root cause

Effort vocabulary and availability are modeled globally, although they are provider- and model-specific. The adapter already reads model/list, but only retains each model's default effort and discards supportedReasoningEfforts.

Fix

  • Represent Codex ultra distinctly from Claude ultracode.
  • Carry supported/default effort metadata from the provider model catalog through the normalized contract.
  • Validate selections against the active provider/model rather than a global static assumption.
  • Update the wire version and all peers in lockstep.
  • Refresh the adapter documentation from the pinned app-server output.

Acceptance

  • Sol/Terra expose and accept max and ultra; Luna exposes and accepts max but not ultra.
  • Configured/runtime ultra remains truthfully reflected.
  • Claude, Grok Build, and other adapters reject values outside their own capabilities.
  • Tests cover provider/model-specific option sets, startup reflection, live switching, and wire validation.

Evidence

Verified directly against the repository-pinned codex-cli 0.144.1 using app-server generate-ts --experimental and a live model/list request on 2026-07-19.

Review in Linear

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@lucas77778
lucas77778 requested review from AprilNEA and Zerlight July 21, 2026 10:20
@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR aligns reasoning-effort handling with each provider and model. The main changes are:

  • Adds Codex’s distinct ultra effort level and per-model defaults.
  • Loads Codex model capabilities before and during sessions.
  • Validates model and effort selections against available metadata.
  • Preserves pending selections across stale updates and recovery.
  • Updates UI effort filtering and bumps the wire protocol to v44.

Confidence Score: 5/5

This looks safe to merge.

Optional or empty Codex catalogs no longer block session startup. Pending model selections survive stale updates and process recovery. No blocking issues were found in the changed code.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the project tests with pnpm test and completed with exit status 0 after about 169.5 seconds.
  • Opened the test run log artifact to verify the command output and confirm the successful test run.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
packages/host/agent-adapter/src/native/codex/adapter.ts Adds Codex catalog normalization, capability validation, and pending selection reconciliation.
packages/foundation/schema/src/model/agent/input.ts Adds ultra and per-model default effort metadata to the agent schema.
packages/foundation/schema/src/wire/message.ts Bumps the wire protocol to version 44 for the schema changes.
packages/presentation/ui/src/shell/agent-efforts.ts Builds effort choices from each model’s advertised capabilities.
packages/presentation/ui/src/shell/new-session-surface.tsx Drops remembered efforts that the selected model does not support.

Reviews (5): Last reviewed commit: "fix(agent): resolve effort review blocke..." | Re-trigger Greptile

Comment thread packages/host/agent-adapter/src/native/codex/adapter.ts Outdated
Comment thread packages/host/agent-adapter/src/native/codex/adapter.ts
Co-authored-by: Chenyu Lu <chenyu@arcbox.dev>
Copilot AI review requested due to automatic review settings July 21, 2026 10:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread packages/host/agent-adapter/src/native/codex/adapter.ts Outdated
Co-authored-by: Chenyu Lu <chenyu@arcbox.dev>
Copilot AI review requested due to automatic review settings July 21, 2026 11:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread packages/host/agent-adapter/src/native/codex/adapter.ts Outdated
Co-authored-by: Chenyu Lu <chenyu@arcbox.dev>
Copilot AI review requested due to automatic review settings July 21, 2026 11:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Zerlight Zerlight left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for two correctness issues:

  1. The inline comment covers the live pending-selection lifetime.
  2. The static fallback capability metadata is not used by draft submission. new-session-surface.tsx:169-174 resolves modelOption only from dynamicModels, while this PR adds model-specific fallback capabilities in agent-models.ts:90-108. If model/list is unavailable, a remembered Sol ultra selection can survive after selecting Luna and is submitted even though the fallback table excludes it, causing the first turn to fail. Resolve the selected model from the dynamic catalog or AGENT_MODEL_OPTIONS[provider] consistently before calculating constrainedEffort.

The pinned 0.144.1 protocol shape and CI both check out; these are the remaining blockers.

Comment thread packages/host/agent-adapter/src/native/codex/adapter.ts Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 06:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copy link
Copy Markdown
Member Author

Addressed the second review blocker in cd7cb81. NewSessionSurface now resolves the selected model from the non-empty dynamic catalog or the same AGENT_MODEL_OPTIONS[provider] fallback used by Composer, through resolveModel, before calculating constrainedEffort. When model/list is unavailable, switching a remembered Sol/ultra draft to Luna now drops the incompatible effort and omits it from submission. Added a regression for that exact flow. pnpm check:ci and the full suite (210 files / 1,641 tests) pass.

# Conflicts:
#	packages/foundation/schema/src/wire/message.ts
#	packages/foundation/schema/tests/contract/wire/agent.test.ts
#	packages/host/agent-adapter/src/__tests__/codex-shell.test.ts
#	packages/host/agent-adapter/src/native/codex/adapter.ts
#	packages/presentation/ui/src/shell/new-session-surface.tsx
Copilot AI review requested due to automatic review settings July 28, 2026 12:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@lucas77778
lucas77778 requested a review from Zerlight July 28, 2026 12:27

@Zerlight Zerlight left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for one remaining correctness issue and one documentation inconsistency.

The previous model-pending fix and the static fallback fix look correct, but the equivalent resume-confirmation path for pendingEffort is still incomplete. A focused adapter regression reproduces the stale reflection deterministically.

Verification on this head: the full test suite passed (244 files, 1,965 tests; 3 files and 5 tests skipped), pnpm check:ci passed, git diff --check passed, and all GitHub checks are green.

if (this.effort !== undefined) {
this.assertEffortSupported(this.effort, this.model ?? model, !this.modelCatalogAvailable);
}
if (this.pendingEffort !== undefined) return;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Clear an effort confirmed by thread/resume

BaseAgentAdapter.start() calls onSetEffort() before onStart(), so resuming with a remembered effort such as high sets pendingEffort before thread/resume. If the resume response already reports high, this early return leaves the marker set. The app-server only emits thread/settings/updated when the effective settings actually change, so another matching high notification is not guaranteed. A later authoritative correction to medium then reaches the pending-effort branch and is discarded indefinitely, leaving the engine/UI cache at high.

Resolve the response effort (or model default) before returning and clear pendingEffort when it matches, paralleling the pendingModel handling above. I reproduced this with the existing TestCodex fixture: after a resume response with high, a medium settings update emitted no effort-update, both inside and outside the sandbox.

- **Approval-policy axis** (three tiers; claude-only ids like `plan`/`auto` reject): `default`→untrusted + workspace-write, `acceptEdits` (initial)→on-request + workspace-write, `bypassPermissions`→never + danger-full-access. Applied per `turn/start` — next-turn semantics, same channel as model/effort; nothing can alter an in-flight turn.
- **config.toml contract**: `codexConfiguredSandbox()` (`codex/config.ts`; exercised via a throwaway `CODEX_HOME` in `codex-config.test.ts`) reads the active profile's or top-level `sandbox_mode`. Until the user EXPLICITLY picks a tier, a configured sandbox is never overridden — thread/turn requests omit their sandbox override so codex's own resolution wins (NEVER silently loosen a stricter read-only); the preset's approval posture still rides, which is safe now that approvals are answerable. An explicit pick applies the preset exactly, config.toml notwithstanding. Honoring config.toml `approval_policy` stays an unfinished follow-up.
- **set-model / set-effort** are stored and sent as `turn/start` overrides (they stick for subsequent turns). Effort accepts `low`–`xhigh`; `max`/`ultracode` are claude-only and reject. The picker entries are the static UI tables (`agent-models.ts` / `agent-efforts.ts`), each verified live via `turn_context` readback. At startup, the adapter reflects the `thread/start`/`thread/resume` response's model and configured effort; a null effort resolves through that model's `model/list.defaultReasoningEffort` without pinning it as an override. `thread/settings/updated` is the ongoing effective model/effort authority. The rest of the dynamic catalog remains deliberately unused (the CODE-104 attempt was cancelled).
- **set-model / set-effort** are stored and sent as `turn/start` overrides (they stick for subsequent turns). Effort availability comes from each `model/list` entry's `supportedReasoningEfforts`: Sol/Terra advertise `low|medium|high|xhigh|max|ultra`, while Luna omits `ultra`; `minimal` is outside LinkCode's normalized vocabulary and Claude's distinct `ultracode` always rejects. The adapter publishes that per-model catalog both before session start and on the live event stream, and validates startup/live selections against the selected model. If optional `model/list` discovery is unavailable, validation defers to Codex instead of blocking session start. At startup, it reflects the `thread/start`/`thread/resume` response's model and configured effort; a null effort resolves through that model's `model/list.defaultReasoningEffort` without pinning it as an override. `thread/settings/updated` reflects effective provider state unless it conflicts with a newer pending next-turn pick. Switches apply from the next turn, not mid-turn.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Keep the capability matrix in sync

This paragraph now documents model-specific max and ultra support, but the capability matrix below still says Codex supports only low–xhigh. Please update the Codex row so the package's reference documentation agrees with the adapter and UI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants