Repository navigation
feat: add Codex agent adapter - #154
leonininder wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
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` | |
There was a problem hiding this comment.
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>
| | `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. |
There was a problem hiding this comment.
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>
| # 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 |
There was a problem hiding this comment.
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>
| "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 |
| elif action == "sdk": | ||
| sdk_choices = [ | ||
| Choice(title="claude", value="claude"), | ||
| Choice(title="codex", value="codex"), |
There was a problem hiding this comment.
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 ( |
There was a problem hiding this comment.
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>
| 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" |
There was a problem hiding this comment.
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). |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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>
| 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. |
| - **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. |
There was a problem hiding this comment.
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>
| - **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. |
| "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 " |
There was a problem hiding this 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.
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.
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.| har_base = str(self.har_path.parent.parent) | ||
| return self._codex_mcp_overrides( | ||
| "playwright", | ||
| command, | ||
| args, | ||
| env={"PLAYWRIGHT_MCP_SAVE_HAR_PATH": har_base}, |
There was a problem hiding this 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
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.
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.| "--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"], |
There was a problem hiding this comment.
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.
- 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.
- 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.
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.| return {} | ||
| prompt = opening if self.resume_session else f"{system_prompt}\n\n{user_message}" | ||
| return await self._run_codex(prompt) |
There was a problem hiding this 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
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.
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.
Summary
sdk="codex"adapter that reuses the local Codex CLI sign-in and prefers Codex Desktop's bundled CLI on Windows.gpt-6-luna), session/history usage reporting, resume dispatch, and Codex login/browser-provider preflight.agent_provider="auto"; require an observed MCP browser call and a non-empty HAR before reporting capture success.Verification
git diff --check: passed.0.166.0-alpha.5.1acceptedgpt-6-lunaand returnedOK(18,542 input tokens, 11,776 cached, 5 output tokens).5bbef964224awas completed withgpt-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.test_no_tty_no_subcommand_exits_2[utf-8], 10-seconduv runlimit); 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-lunabecause 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 ongpt-6.1-sol.Files
src/reverse_api/codex_engineer.py,tests/test_codex_engineer.py.src/reverse_api/cli.py,src/reverse_api/config.py,src/reverse_api/engineer.py,src/reverse_api/prompts/auto/system.md.tests/test_cli_followups.py,tests/test_cli_agent_json.py,tests/test_engineer.py.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.
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
Fix with agent prompt
Summary
Adds Codex as a selectable backend for capture and HAR-based generation.
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