Skip to content

feat: add Codex agent adapter - #154

Open
leonininder wants to merge 1 commit into
kalil0321:mainfrom
leonininder:leon/codex-adapter-gpt-6-luna
Open

leonininder wants to merge 1 commit into
kalil0321:mainfrom
leonininder:leon/codex-adapter-gpt-6-luna

Conversation

@leonininder

@leonininder leonininder commented Nov 2, 2026 •

Copy link
Copy Markdown

Summary

  • Add a native sdk="codex" adapter that reuses the local Codex CLI sign-in and prefers Codex Desktop's bundled CLI on Windows.
  • Add RAE CLI/configuration support, model selection (default gpt-6-luna), session/history usage reporting, resume dispatch, and Codex login/browser-provider preflight.
  • Provide Playwright MCP configuration per Codex invocation for agent_provider="auto"; require an observed MCP browser call and a non-empty HAR before reporting capture success.
  • Add adapter/CLI tests and document the setup and limitations. A ranked-list prompt rule safely omits only unidentified all-zero aggregate rows.

Verification

  • Codex-specific focused tests: 13 passed.
  • Ruff on changed Python modules and tests: passed.
  • Staged git diff --check: passed.
  • Codex Desktop CLI 0.166.0-alpha.5.1 accepted gpt-6-luna and returned OK (18,542 input tokens, 11,776 cached, 5 output tokens).
  • Prior end-to-end RAE capture 5bbef964224a was completed with gpt-6.1-sol: seven Playwright MCP calls, a 179-entry HAR, public endpoint HTTP 200 / 672 rows, and a reviewed client whose top 15 IDs/token totals matched the captured response sidecar. No OpenRouter API key, login, cookie, or API credential was used.
  • A broader selected regression run had 200 passes and one unrelated UTF-8 TTY-detection test timeout (test_no_tty_no_subcommand_exits_2[utf-8], 10-second uv run limit); one pre-existing Claude interruption coroutine warning appeared. The full repository suite was not run.

The complete browser E2E was not repeated with gpt-6-luna because the prior run reported 587,099 input tokens. Luna-specific verification in this contribution is a short CLI smoke call plus focused tests; the previous full RAE flow is evidence for the adapter on gpt-6.1-sol.

Files

  • New: src/reverse_api/codex_engineer.py, tests/test_codex_engineer.py.
  • Updated: src/reverse_api/cli.py, src/reverse_api/config.py, src/reverse_api/engineer.py, src/reverse_api/prompts/auto/system.md.
  • Coverage: tests/test_cli_followups.py, tests/test_cli_agent_json.py, tests/test_engineer.py.
  • Documentation: README.md, skills/reverse-api-engineer/SKILL.md, skills/reverse-api-engineer/references/setup.md.

Attribution

This implementation was prepared with Codex assistance at Leon's request. Leon reviewed the end-to-end evidence and requests contributor credit for the feature request and validation if the PR is accepted.

RetriggerView in GreptileConfidence Score: 3/5

The conflicting capture instructions and relative-output failures must be fixed before merging; the browser-visibility and follow-up issues are non-blocking on their own.

Findings

  1. P1 Every capture gets rankings instructions ▶
  2. P1 Relative paths target wrong folders ▶
  3. P2 Browser always runs hidden ▶
  4. P2 Interactive runs skip follow-ups ▶
Fix with agent prompt
### Issue 1
src/reverse_api/codex_engineer.py:466-469
Every Codex capture is told to find “the rankings GET request” and return only its first 15 rows, even when the user requests an unrelated API. Executing prompt construction for a weather client requesting all 48 hourly records confirmed that these conflicting instructions reach Codex alongside the user's task. This can divert capture from the requested endpoints or restrict the requested results. Remove these task-specific instructions before merging, or include them only when the user requests them.

### Issue 2
src/reverse_api/codex_engineer.py:494-499
With a relative output directory such as `-o runs`, the prompt and browser environment retain paths such as `runs/scripts/<run-id>` and `runs/har`, but Codex starts inside the resolved `runs` directory. Those paths consequently point beneath `runs/runs`, while Python checks the original locations. Executing the adapter with controlled child processes reproduced both the missing-HAR and missing-client failures; the same flow succeeded with an absolute output directory. Resolve output-derived paths before passing them to Codex or its browser server. This needs fixing before merging because a supported output-directory choice causes generation to report failure.

### Issue 3
src/reverse_api/codex_engineer.py:482-491
Both launch branches always include `--headless`, although the constructor accepts and saves `headless=False`. Users therefore cannot watch a Codex capture in a visible browser, even when they leave `--headless` off. Argument-generation checks confirmed this for both branches, and a Chromium probe using the generated setting confirmed headless operation. This is a non-blocking option-handling defect; add the flag only when `self.headless` is true.

### Issue 4
src/reverse_api/codex_engineer.py:415-417
Both Codex entry points return immediately after the first turn instead of offering the shared follow-up prompt. Executing interactive generation and capture confirmed that neither asks for another message, including after resuming a session. Users must explicitly resume the run for each refinement rather than continuing the open conversation. This is a non-blocking interaction limitation; add a follow-up loop that reuses the recorded Codex session and keeps the latest successful result.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Adds Codex as a selectable backend for capture and HAR-based generation.

  • Codex can generate clients from HAR files or browser captures.
  • Automatic agents follow a shared rule for unidentified ranked-list rows.

Merge assessment: not ready to merge until the task-specific capture instructions and relative-path failures are fixed.

Reviews (1) · Last reviewed commit: "feat: add Codex agent adapter" · Reviewed by Greptile

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

14 issues found across 12 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="skills/reverse-api-engineer/SKILL.md">

<violation number="1" location="skills/reverse-api-engineer/SKILL.md:48">
P3: The Codex example doesn't fit this sentence. Codex never gets an API-key `warn`; its preflight reports `sdk:codex` login status instead. Consider dropping "or Codex CLI" here, since the Codex login is covered by the new paragraph below.</violation>
</file>

<file name="skills/reverse-api-engineer/references/setup.md">

<violation number="1" location="skills/reverse-api-engineer/references/setup.md:20">
P2: The Desktop-bundled CLI preference only exists on Windows (`resolve_codex_command` returns early only under `sys.platform == "win32"`). Qualify this row, for example "on Windows, Codex Desktop's bundled CLI is preferred when present; otherwise `codex` on `PATH`."</violation>

<violation number="2" location="skills/reverse-api-engineer/references/setup.md:22">
P3: `-m/--model` now also applies to the `codex` SDK, but the Settings intro still says it is for the `claude` SDK only. Update that sentence ("Only two have per-run flags on `agent`... `-m/--model` (for the `claude` and `codex` SDKs)") so the two passages agree.</violation>

<violation number="3" location="skills/reverse-api-engineer/references/setup.md:22">
P2: `--model` is not a usable Codex model override: the agent option accepts only Claude model IDs, so it rejects `gpt-6-luna` and arbitrary Codex IDs. Remove `--model` from this Codex documentation or make the CLI's model validation SDK-aware.</violation>
</file>

<file name="src/reverse_api/prompts/auto/system.md">

<violation number="1" location="src/reverse_api/prompts/auto/system.md:21">
P2: This ranked-list rule is task-specific but sits in the generic system prompt, so it applies to every capture. Move it to the rankings-specific user message, as `codex_engineer.py` already does, and drop it from `system.md`. Also define what "fail" means if the rule is kept.</violation>
</file>

<file name="src/reverse_api/config.py">

<violation number="1" location="src/reverse_api/config.py:30">
P2: The comment is wrong: `None` does not defer to the Codex CLI's default. It resolves to `gpt-6-luna` and is passed as `--model`. To use the CLI's own default, set `"default"`. Update the comment to match.</violation>
</file>

<file name="src/reverse_api/engineer.py">

<violation number="1" location="src/reverse_api/engineer.py:437">
P3: The `codex_model` docstring says `None` uses the Codex CLI's configured default, but it doesn't. `None` falls back to `model`, then to the hardcoded `gpt-6-luna`, and `--model` is always passed. Update the docstring to describe that fallback.</violation>
</file>

<file name="src/reverse_api/cli.py">

<violation number="1" location="src/reverse_api/cli.py:929">
P2: Choosing codex in /settings leaves `agent_provider` at its default `chrome-mcp`, so every `agent` run then fails in `CodexAutoEngineer` with the "requires agent_provider='auto'" error. When the codex sdk is selected, also set `agent_provider` to `auto`, or block the selection with a clear message.</violation>

<violation number="2" location="src/reverse_api/cli.py:1758">
P2: Resumed Codex captures are written under a timestamped HAR directory but that path is not persisted or used by the JSON payload. Preserve the returned HAR path in run history and have payload construction use it.</violation>
</file>

<file name="src/reverse_api/codex_engineer.py">

<violation number="1" location="src/reverse_api/codex_engineer.py:198">
P2: Codex's `input_tokens` appears to include `cached_input_tokens`, but both are stored as separate buckets, so cached tokens are double counted in the token total and the estimated cost. Subtract the cached count from `input_tokens` before storing it, after confirming Codex's semantics.</violation>

<violation number="2" location="src/reverse_api/codex_engineer.py:417">
P2: Codex runs stop after the first turn and never offer the interactive follow-up supported by the base engineer flow. Process follow-up messages by resuming the Codex session until the user finishes.</violation>

<violation number="3" location="src/reverse_api/codex_engineer.py:482">
P2: `headless` is parsed and stored, but `_playwright_mcp_overrides` hardcodes `--headless`, so the Codex capture always runs headless. Gate the flag on `self.headless` as `auto_engineer.py` does.</violation>

<violation number="4" location="src/reverse_api/codex_engineer.py:491">
P2: Codex auto capture always launches Playwright with `--headless`, so the normal headed mode is ignored. Add this flag only when `self.headless` is true.</violation>
</file>

<file name="README.md">

<violation number="1" location="README.md:132">
P3: The bundled Codex CLI preference is implemented only on Windows, but this documentation presents it as platform-independent. Qualify the preference as Windows-only, or implement bundled-CLI discovery on the other supported platforms.</violation>
</file>

Reply to a comment to ask cubic a question or push back. It learns from your replies.

View guided diff | Re-trigger cubic

| `opencode` | An OpenCode server rae starts or reuses. Defaults to a free model; can route to local models through Ollama |
| `copilot` | GitHub Copilot credentials (`GITHUB_COPILOT_TOKEN`) |
| `cursor` | `CURSOR_API_KEY` |
| `codex` | Existing local Codex CLI login; Codex Desktop's bundled CLI is preferred when present, then `codex` on `PATH` |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The Desktop-bundled CLI preference only exists on Windows (resolve_codex_command returns early only under sys.platform == "win32"). Qualify this row, for example "on Windows, Codex Desktop's bundled CLI is preferred when present; otherwise codex on PATH."

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/reverse-api-engineer/references/setup.md, line 20:

<comment>The Desktop-bundled CLI preference only exists on Windows (`resolve_codex_command` returns early only under `sys.platform == "win32"`). Qualify this row, for example "on Windows, Codex Desktop's bundled CLI is preferred when present; otherwise `codex` on `PATH`."</comment>

<file context>
@@ -17,8 +17,9 @@ rae calls a model through the SDK selected in its config:
 | `opencode` | An OpenCode server rae starts or reuses. Defaults to a free model; can route to local models through Ollama |
 | `copilot` | GitHub Copilot credentials (`GITHUB_COPILOT_TOKEN`) |
 | `cursor` | `CURSOR_API_KEY` |
+| `codex` | Existing local Codex CLI login; Codex Desktop's bundled CLI is preferred when present, then `codex` on `PATH` |
 
-`agent --dry-run` reports which of these it can see. A missing env var is a warning, not an error, because some SDKs find credentials on their own.
</file context>
Suggested change
| `codex` | Existing local Codex CLI login; Codex Desktop's bundled CLI is preferred when present, then `codex` on `PATH` |
| `codex` | Existing local Codex CLI login; on Windows, Codex Desktop's bundled CLI is preferred when present, then `codex` on `PATH` |

- Narrate your actions as you browse
- Capture all necessary API calls before generating code
- Test your generated code to verify it works
- For ranked lists, omit unidentified rows only when their ranking metric and activity counters are all zero, and report the omission; fail on unidentified nonzero rows.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This ranked-list rule is task-specific but sits in the generic system prompt, so it applies to every capture. Move it to the rankings-specific user message, as codex_engineer.py already does, and drop it from system.md. Also define what "fail" means if the rule is kept.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/reverse_api/prompts/auto/system.md, line 21:

<comment>This ranked-list rule is task-specific but sits in the generic system prompt, so it applies to every capture. Move it to the rankings-specific user message, as `codex_engineer.py` already does, and drop it from `system.md`. Also define what "fail" means if the rule is kept.</comment>

<file context>
@@ -18,10 +18,11 @@ For this provider your integration surface is:
 - Narrate your actions as you browse
 - Capture all necessary API calls before generating code
 - Test your generated code to verify it works
+- For ranked lists, omit unidentified rows only when their ranking metric and activity counters are all zero, and report the omission; fail on unidentified nonzero rows.
 - Screenshots must be under 1MB — prefer element-specific screenshots or use snapshots for structure
 
</file context>

Comment thread src/reverse_api/config.py
# Optional override: list of setting source ids, e.g. ["project","user","all"]. None uses cursor_web_search.
"cursor_setting_sources": None,
"copilot_model": "gpt-5", # Model for Copilot SDK sessions
"codex_model": None, # None uses the default model selected by the local Codex CLI

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The comment is wrong: None does not defer to the Codex CLI's default. It resolves to gpt-6-luna and is passed as --model. To use the CLI's own default, set "default". Update the comment to match.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/reverse_api/config.py, line 30:

<comment>The comment is wrong: `None` does not defer to the Codex CLI's default. It resolves to `gpt-6-luna` and is passed as `--model`. To use the CLI's own default, set `"default"`. Update the comment to match.</comment>

<file context>
@@ -27,6 +27,7 @@
     # Optional override: list of setting source ids, e.g. ["project","user","all"]. None uses cursor_web_search.
     "cursor_setting_sources": None,
     "copilot_model": "gpt-5",  # Model for Copilot SDK sessions
+    "codex_model": None,  # None uses the default model selected by the local Codex CLI
     "opencode_model": DEFAULT_OPENCODE_MODEL,
     "opencode_provider": DEFAULT_OPENCODE_PROVIDER,
</file context>
Suggested change
"codex_model": None, # None uses the default model selected by the local Codex CLI
"codex_model": None, # None uses the default Codex model (gpt-6-luna); "default" defers to the local Codex CLI

Comment thread src/reverse_api/cli.py
elif action == "sdk":
sdk_choices = [
Choice(title="claude", value="claude"),
Choice(title="codex", value="codex"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Choosing codex in /settings leaves agent_provider at its default chrome-mcp, so every agent run then fails in CodexAutoEngineer with the "requires agent_provider='auto'" error. When the codex sdk is selected, also set agent_provider to auto, or block the selection with a clear message.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/reverse_api/cli.py, line 929:

<comment>Choosing codex in /settings leaves `agent_provider` at its default `chrome-mcp`, so every `agent` run then fails in `CodexAutoEngineer` with the "requires agent_provider='auto'" error. When the codex sdk is selected, also set `agent_provider` to `auto`, or block the selection with a clear message.</comment>

<file context>
@@ -906,6 +926,7 @@ def _handle_settings_action(mode_color: str = THEME_PRIMARY) -> bool:  # noqa: C
     elif action == "sdk":
         sdk_choices = [
             Choice(title="claude", value="claude"),
+            Choice(title="codex", value="codex"),
             Choice(title="copilot", value="copilot"),
             Choice(title="cursor", value="cursor"),
</file context>

if event_type == "turn.completed":
usage = event.get("usage")
if isinstance(usage, dict):
for source, target in (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Codex's input_tokens appears to include cached_input_tokens, but both are stored as separate buckets, so cached tokens are double counted in the token total and the estimated cost. Subtract the cached count from input_tokens before storing it, after confirming Codex's semantics.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/reverse_api/codex_engineer.py, line 198:

<comment>Codex's `input_tokens` appears to include `cached_input_tokens`, but both are stored as separate buckets, so cached tokens are double counted in the token total and the estimated cost. Subtract the cached count from `input_tokens` before storing it, after confirming Codex's semantics.</comment>

<file context>
@@ -0,0 +1,515 @@
+        if event_type == "turn.completed":
+            usage = event.get("usage")
+            if isinstance(usage, dict):
+                for source, target in (
+                    ("input_tokens", "input_tokens"),
+                    ("cached_input_tokens", "cache_read_tokens"),
</file context>

Comment thread src/reverse_api/cli.py
if hasattr(engineer, "mcp_run_id"):
engineer.mcp_run_id = f"{run_id}-{int(time.time())}"
if sdk == "codex":
engineer.har_path = get_har_dir(engineer.mcp_run_id, output_dir) / "recording.har"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Resumed Codex captures are written under a timestamped HAR directory but that path is not persisted or used by the JSON payload. Preserve the returned HAR path in run history and have payload construction use it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/reverse_api/cli.py, line 1758:

<comment>Resumed Codex captures are written under a timestamped HAR directory but that path is not persisted or used by the JSON payload. Preserve the returned HAR path in run history and have payload construction use it.</comment>

<file context>
@@ -1704,7 +1752,10 @@ def run_auto_capture(
+            if hasattr(engineer, "mcp_run_id"):
+                engineer.mcp_run_id = f"{run_id}-{int(time.time())}"
+            if sdk == "codex":
+                engineer.har_path = get_har_dir(engineer.mcp_run_id, output_dir) / "recording.har"
 
         if json_event_sink is not None:
</file context>

```

This validates the prompt, URL, config and environment without opening a browser. Fix every `error` check before running. A `warn` on the API key is fine when the SDK authenticates another way (for example a logged-in Claude Code).
This validates the prompt, URL, config and environment without opening a browser. Fix every `error` check before running. A `warn` on the API key is fine when the SDK authenticates another way (for example a logged-in Claude Code or Codex CLI).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The Codex example doesn't fit this sentence. Codex never gets an API-key warn; its preflight reports sdk:codex login status instead. Consider dropping "or Codex CLI" here, since the Codex login is covered by the new paragraph below.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/reverse-api-engineer/SKILL.md, line 48:

<comment>The Codex example doesn't fit this sentence. Codex never gets an API-key `warn`; its preflight reports `sdk:codex` login status instead. Consider dropping "or Codex CLI" here, since the Codex login is covered by the new paragraph below.</comment>

<file context>
@@ -45,10 +45,12 @@ reverse-api-engineer show <run_id> --json

-This validates the prompt, URL, config and environment without opening a browser. Fix every error check before running. A warn on the API key is fine when the SDK authenticates another way (for example a logged-in Claude Code).
+This validates the prompt, URL, config and environment without opening a browser. Fix every error check before running. A warn on the API key is fine when the SDK authenticates another way (for example a logged-in Claude Code or Codex CLI).

would_run.agent_provider in the output is the browser the run will use. chrome-mcp means the user's own Chrome with their logins; auto and agent-browser start a fresh browser without them. When the task needs the user's login and the provider is not chrome-mcp, ask before switching it (see sessions).
</file context>


</details>

```suggestion
This validates the prompt, URL, config and environment without opening a browser. Fix every `error` check before running. A `warn` on the API key is fine when the SDK authenticates another way (for example a logged-in Claude Code).

| `codex` | Existing local Codex CLI login; Codex Desktop's bundled CLI is preferred when present, then `codex` on `PATH` |

`agent --dry-run` reports which of these it can see. A missing env var is a warning, not an error, because some SDKs find credentials on their own.
`agent --dry-run` reports which of these it can see. A missing env var is a warning, not an error, because some SDKs find credentials on their own. Codex defaults to `gpt-6-luna` unless `codex_model` or `--model` overrides it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: -m/--model now also applies to the codex SDK, but the Settings intro still says it is for the claude SDK only. Update that sentence ("Only two have per-run flags on agent... -m/--model (for the claude and codex SDKs)") so the two passages agree.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/reverse-api-engineer/references/setup.md, line 22:

<comment>`-m/--model` now also applies to the `codex` SDK, but the Settings intro still says it is for the `claude` SDK only. Update that sentence ("Only two have per-run flags on `agent`... `-m/--model` (for the `claude` and `codex` SDKs)") so the two passages agree.</comment>

<file context>
@@ -17,8 +17,9 @@ rae calls a model through the SDK selected in its config:
+| `codex` | Existing local Codex CLI login; Codex Desktop's bundled CLI is preferred when present, then `codex` on `PATH` |
 
-`agent --dry-run` reports which of these it can see. A missing env var is a warning, not an error, because some SDKs find credentials on their own.
+`agent --dry-run` reports which of these it can see. A missing env var is a warning, not an error, because some SDKs find credentials on their own. Codex defaults to `gpt-6-luna` unless `codex_model` or `--model` overrides it.
 
 ## Settings
</file context>

opencode_model: Model ID for OpenCode (e.g., "claude-sonnet-4-6")
copilot_model: Model ID for Copilot (e.g., "gpt-5")
cursor_model: Model id for Cursor SDK (e.g., "composer-2.5")
codex_model: Optional model id for the local Codex CLI; None uses its configured default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The codex_model docstring says None uses the Codex CLI's configured default, but it doesn't. None falls back to model, then to the hardcoded gpt-6-luna, and --model is always passed. Update the docstring to describe that fallback.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/reverse_api/engineer.py, line 437:

<comment>The `codex_model` docstring says `None` uses the Codex CLI's configured default, but it doesn't. `None` falls back to `model`, then to the hardcoded `gpt-6-luna`, and `--model` is always passed. Update the docstring to describe that fallback.</comment>

<file context>
@@ -428,11 +429,12 @@ def run_reverse_engineering(
         opencode_model: Model ID for OpenCode (e.g., "claude-sonnet-4-6")
         copilot_model: Model ID for Copilot (e.g., "gpt-5")
         cursor_model: Model id for Cursor SDK (e.g., "composer-2.5")
+        codex_model: Optional model id for the local Codex CLI; None uses its configured default.
         cursor_web_search: When True, load extra Cursor setting layers so WebFetch/WebSearch and plugins apply.
         cursor_setting_sources: Optional explicit list (overrides cursor_web_search), e.g. ["project","user","all"].
</file context>
Suggested change
codex_model: Optional model id for the local Codex CLI; None uses its configured default.
codex_model: Optional model id for the local Codex CLI; None falls back to model, then gpt-6-luna.

Comment thread README.md
- **Models**: Sonnet 5.5, Opus 5.5 (most capable), Opus 4.6 and Haiku 5.5 (fastest). Sonnet 4.6 stays the default until you choose another; it and Haiku 4.5 are still accepted in config and by `--model`. For OpenCode see [models.dev](https://models.dev).
- **SDK**: `claude` (default), `opencode`, `cursor`, or `copilot` (GitHub Copilot).
- **SDK**: `claude` (default), `opencode`, `cursor`, `copilot` (GitHub Copilot), or `codex`.
- **Codex SDK**: `sdk: "codex"` reuses the local Codex CLI login, preferring the Codex Desktop-bundled CLI and falling back to `codex` on `PATH`. `codex_model` is optional; RAE defaults to `gpt-6-luna`. Codex browser capture currently requires `agent_provider: "auto"`, which provides Playwright MCP and a HAR. The adapter supplies per-run MCP configuration and does not edit the global Codex config.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The bundled Codex CLI preference is implemented only on Windows, but this documentation presents it as platform-independent. Qualify the preference as Windows-only, or implement bundled-CLI discovery on the other supported platforms.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At README.md, line 132:

<comment>The bundled Codex CLI preference is implemented only on Windows, but this documentation presents it as platform-independent. Qualify the preference as Windows-only, or implement bundled-CLI discovery on the other supported platforms.</comment>

<file context>
@@ -127,7 +128,8 @@ Settings live in `~/.reverse-api/config.json` and can be edited via `/settings`
 - **Models**: Sonnet 5.5, Opus 5.5 (most capable), Opus 4.6 and Haiku 5.5 (fastest). Sonnet 4.6 stays the default until you choose another; it and Haiku 4.5 are still accepted in config and by `--model`. For OpenCode see [models.dev](https://models.dev).
-- **SDK**: `claude` (default), `opencode`, `cursor`, or `copilot` (GitHub Copilot).
+- **SDK**: `claude` (default), `opencode`, `cursor`, `copilot` (GitHub Copilot), or `codex`.
+- **Codex SDK**: `sdk: "codex"` reuses the local Codex CLI login, preferring the Codex Desktop-bundled CLI and falling back to `codex` on `PATH`. `codex_model` is optional; RAE defaults to `gpt-6-luna`. Codex browser capture currently requires `agent_provider: "auto"`, which provides Playwright MCP and a HAR. The adapter supplies per-run MCP configuration and does not edit the global Codex config.
 - **Claude settings isolation**: Claude sessions don't load your Claude Code settings files, `CLAUDE.md`, hooks, plugins, permission rules or MCP servers, so your personal setup doesn't steer the agent. Organization-managed policy still applies, and Claude Code still reads its own state such as `~/.claude.json` and auto memory. If `~/.claude/settings.json` provides your authentication (`apiKeyHelper`, or Bedrock, Vertex or proxy variables under `env`), set `claude_setting_sources` to the layers to load, e.g. `["user"]` or `["user", "project", "local"]`. Each layer you list is loaded in full, including its hooks, plugins, permission rules and MCP servers.
 - **OpenCode setup**: with `sdk: "opencode"`, RAE reuses an existing server or downloads/starts `opencode-ai@latest` through `npx`; a global OpenCode installation is not required. Fresh configurations default to the free `opencode/big-pickle` model. `/settings` shows a loading spinner, then offers a searchable **OpenCode Provider / Model** picker populated from the server's connected, tool-capable catalog and marks free OpenCode options. Before creating a session, RAE validates the saved pair again and suggests currently available free models when configuration is invalid. Compatible older servers are reused with a version warning. Node.js 20+ is required for automatic startup. Password-protected servers use `OPENCODE_SERVER_PASSWORD` and optional `OPENCODE_SERVER_USERNAME`. Override startup with `OPENCODE_BASE_URL`, `RAE_OPENCODE_PACKAGE`, or `RAE_OPENCODE_AUTO_START=0`.
</file context>
Suggested change
- **Codex SDK**: `sdk: "codex"` reuses the local Codex CLI login, preferring the Codex Desktop-bundled CLI and falling back to `codex` on `PATH`. `codex_model` is optional; RAE defaults to `gpt-6-luna`. Codex browser capture currently requires `agent_provider: "auto"`, which provides Playwright MCP and a HAR. The adapter supplies per-run MCP configuration and does not edit the global Codex config.
- **Codex SDK**: `sdk: "codex"` reuses the local Codex CLI login. On Windows, it prefers the Codex Desktop-bundled CLI and falls back to `codex` on `PATH`. `codex_model` is optional; RAE defaults to `gpt-6-luna`. Codex browser capture currently requires `agent_provider: "auto"`, which provides Playwright MCP and a HAR. The adapter supplies per-run MCP configuration and does not edit the global Codex config.

Comment on lines +466 to +469
"Avoid printing the full page body or full network log into the conversation. After identifying "
"the rankings GET request, parse its response in the browser and return only the first 15 rows "
"with the fields needed by the client. Do not assign a rank to unidentified zero-activity aggregate "
"rows; report if one is omitted, and fail closed on malformed nonzero rows. Use the native "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Every capture gets rankings instructions

Every Codex capture is told to find “the rankings GET request” and return only its first 15 rows, even when the user requests an unrelated API. Executing prompt construction for a weather client requesting all 48 hourly records confirmed that these conflicting instructions reach Codex alongside the user's task. This can divert capture from the requested endpoints or restrict the requested results. Remove these task-specific instructions before merging, or include them only when the user requests them.

Artifacts

Executed prompt-construction reproduction source

  • This harness executes the adapter's capture prompt path with an unrelated weather task and captures the runner argument, making the focused comparison reproducible.

Weather prompt with ranking instructions removed in memory

  • The venv executed the controlled adapter method and captured its complete runner prompt with exit code 0, showing the weather request without rankings or first-15 directives.

Weather prompt from the unmodified adapter

  • The venv executed the unmodified adapter method and captured its complete runner prompt with exit code 0, showing that the unrelated weather request receives rankings and first-15 directives.

View artifacts

TREX Ran code and verified through TREX

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/codex_engineer.py
Line: 466-469

Comment:
**Every capture gets rankings instructions**

Every Codex capture is told to find “the rankings GET request” and return only its first 15 rows, even when the user requests an unrelated API. Executing prompt construction for a weather client requesting all 48 hourly records confirmed that these conflicting instructions reach Codex alongside the user's task. This can divert capture from the requested endpoints or restrict the requested results. Remove these task-specific instructions before merging, or include them only when the user requests them.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +494 to +499
har_base = str(self.har_path.parent.parent)
return self._codex_mcp_overrides(
"playwright",
command,
args,
env={"PLAYWRIGHT_MCP_SAVE_HAR_PATH": har_base},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Relative paths target wrong folders

With a relative output directory such as -o runs, the prompt and browser environment retain paths such as runs/scripts/<run-id> and runs/har, but Codex starts inside the resolved runs directory. Those paths consequently point beneath runs/runs, while Python checks the original locations. Executing the adapter with controlled child processes reproduced both the missing-HAR and missing-client failures; the same flow succeeded with an absolute output directory. Resolve output-derived paths before passing them to Codex or its browser server. This needs fixing before merging because a supported output-directory choice causes generation to report failure.

Knowledge Base Used: Browser automation

Artifacts

Executed relative-output reproduction source

  • The authored and executed harness constructs the real adapter and runs controlled Codex/browser children, providing reproducible assertions for the path mismatch and absolute-path control.

Relative output run fails artifact validation

  • The captured relative-output execution records child cwd, unchanged prompt and HAR paths, nested filesystem writes, and both real artifact-check failures, supporting candidate1.

Absolute output workaround passes artifact validation

  • The captured absolute-output execution runs the same controlled flow and records aligned artifact paths plus a successful adapter result, isolating relative-path interpretation as the cause.

View artifacts

TREX Ran code and verified through TREX

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/codex_engineer.py
Line: 494-499

Comment:
**Relative paths target wrong folders**

With a relative output directory such as `-o runs`, the prompt and browser environment retain paths such as `runs/scripts/<run-id>` and `runs/har`, but Codex starts inside the resolved `runs` directory. Those paths consequently point beneath `runs/runs`, while Python checks the original locations. Executing the adapter with controlled child processes reproduced both the missing-HAR and missing-client failures; the same flow succeeded with an absolute output directory. Resolve output-derived paths before passing them to Codex or its browser server. This needs fixing before merging because a supported output-directory choice causes generation to report failure.

**Knowledge Base Used:** [Browser automation](https://app.greptile.com/-/switch-tenant?tenant=kalil0321&next=%2Fcustom-context%2Fknowledge-base%2Fkalil0321%2Freverse-api-engineer%2F-%2Fdocs%2Fbrowser-automation.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +482 to +491
"--headless",
"--browser chrome",
]
)
if os.name == "nt":
command, args = shutil.which("cmd.exe") or "cmd.exe", ["/d", "/s", "/c", command_line]
else:
command, args = (
shutil.which("npx") or "npx",
["-y", RAE_PLAYWRIGHT_MCP_PACKAGE, "--run-id", self.mcp_run_id, "--headless", "--browser", "chrome"],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Browser always runs hidden

Both launch branches always include --headless, although the constructor accepts and saves headless=False. Users therefore cannot watch a Codex capture in a visible browser, even when they leave --headless off. Argument-generation checks confirmed this for both branches, and a Chromium probe using the generated setting confirmed headless operation. This is a non-blocking option-handling defect; add the flag only when self.headless is true.

Knowledge Base Used: Browser automation

Artifacts

Executed launch-argument probe source

  • Runs the exact pre-PR method and the real PR constructor and launch method across the requested matrix, making the reproduction repeatable.

Launch arguments for both headless values and platform branches

  • Captures the executed probe’s six observations and successful exit, confirming that only the PR ignores headless=False.

Observed launch settings used by the browser probes

  • Contains machine-readable results emitted by the Python probe and consumed by the Chromium recordings, linking browser behavior to generated settings.

Executed Chromium recording source

  • Launches Chromium using observed settings, checks its actual command line through CDP, and records the same interactive local fixture for comparison.

Executed browser recording launcher

  • Starts Xvfb directly and executes the recording source, allowing a genuine headed baseline without xauth.

▶ Before PR: visible-browser request launches headed Chromium

  • Records the local fixture using the pre-PR generated setting for headless=False, with CDP confirming that Chromium runs without a headless flag.

Before PR browser probe poster

  • Captures the rendered fixture after interaction in headed Chromium under Xvfb, preserving the baseline recording’s poster.

▶ With PR: visible-browser request launches headless Chromium

  • Records the same fixture using the Codex adapter’s generated setting for headless=False, with CDP confirming that Chromium nevertheless runs headless.

With PR browser probe poster

  • Captures the rendered fixture after interaction in headless Chromium, preserving the changed-behavior recording’s poster.

Successful before-and-after Chromium execution record

  • Captures actual CDP flags, browser user agents, and completed interactions for both recordings, independently confirming the launch-mode difference.

Existing Codex adapter tests

  • Records all eight existing Codex tests passing, showing that the current suite does not catch the reproduced option mismatch.

Initial recording attempt blocked by missing xauth

  • Records xvfb-run exiting 3 because xauth is unavailable; direct Xvfb startup subsequently enabled both successful recordings.

View artifacts

TREX Ran code and verified through TREX

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/codex_engineer.py
Line: 482-491

Comment:
**Browser always runs hidden**

Both launch branches always include `--headless`, although the constructor accepts and saves `headless=False`. Users therefore cannot watch a Codex capture in a visible browser, even when they leave `--headless` off. Argument-generation checks confirmed this for both branches, and a Chromium probe using the generated setting confirmed headless operation. This is a non-blocking option-handling defect; add the flag only when `self.headless` is true.

**Knowledge Base Used:** [Browser automation](https://app.greptile.com/-/switch-tenant?tenant=kalil0321&next=%2Fcustom-context%2Fknowledge-base%2Fkalil0321%2Freverse-api-engineer%2F-%2Fdocs%2Fbrowser-automation.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +415 to +417
return {}
prompt = opening if self.resume_session else f"{system_prompt}\n\n{user_message}"
return await self._run_codex(prompt)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Interactive runs skip follow-ups

Both Codex entry points return immediately after the first turn instead of offering the shared follow-up prompt. Executing interactive generation and capture confirmed that neither asks for another message, including after resuming a session. Users must explicitly resume the run for each refinement rather than continuing the open conversation. This is a non-blocking interaction limitation; add a follow-up loop that reuses the recorded Codex session and keeps the latest successful result.

Knowledge Base Used: Engineer core

Artifacts

Focused async follow-up comparison source

  • Authored and executed this harness against production generation and capture entrypoints with controlled turns and terminal input, isolating whether post-turn follow-ups are offered.

Shared entrypoint output with interactive follow-ups

  • Ran eight shared-implementation cases and captured commands, working directory, exit code, and observations; both interactive entrypoints accepted the follow-up and returned the second turn.

Codex entrypoint output without post-turn follow-ups

  • Ran eight matching Codex cases and captured commands, working directory, exit code, and observations; all four interactive cases returned after one turn without offering a post-turn follow-up.

View artifacts

TREX Ran code and verified through TREX

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/reverse_api/codex_engineer.py
Line: 415-417

Comment:
**Interactive runs skip follow-ups**

Both Codex entry points return immediately after the first turn instead of offering the shared follow-up prompt. Executing interactive generation and capture confirmed that neither asks for another message, including after resuming a session. Users must explicitly resume the run for each refinement rather than continuing the open conversation. This is a non-blocking interaction limitation; add a follow-up loop that reuses the recorded Codex session and keeps the latest successful result.

**Knowledge Base Used:** [Engineer core](https://app.greptile.com/-/switch-tenant?tenant=kalil0321&next=%2Fcustom-context%2Fknowledge-base%2Fkalil0321%2Freverse-api-engineer%2F-%2Fdocs%2Fengineer-core.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

This branch has not been deployed

No deployments
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.

1 participant