Skip to content

refactor(codex): drive host-installed codex via the app-server protocol - #137

Open
Waishnav wants to merge 1 commit into
t3code/run-host-installed-codexfrom
t3code/codex-app-server-harness
Open

refactor(codex): drive host-installed codex via the app-server protocol#137
Waishnav wants to merge 1 commit into
t3code/run-host-installed-codexfrom
t3code/codex-app-server-harness

Conversation

@Waishnav

@Waishnav Waishnav commented Aug 7, 2026

Copy link
Copy Markdown
Owner

The first version of the host-CLI Codex runner spawned a one-shot codex exec per turn and parsed a single JSON blob. That loses the streamed item events, depends on the exec JSON shape, and can't preserve a thread across turns without separate bookkeeping.

Codex subagent runs now drive the persistent codex app-server JSON-RPC protocol over the child's stdio, the same harness shape the t3code agent uses: initialize -> initialized -> thread/start (or thread/resume) -> turn/start, then streamed notifications until turn/completed carries the authoritative item list. providerSessionId maps to an app-server thread id, so follow-up turns resume the same ~/.codex/sessions thread across process spawns. Runs stay non-interactive: approvals and other server->client requests are declined.

The protocol lives behind an injectable CodexAppServerWire transport seam, so runCodexAppServerTurn is exercisable offline against a scripted in-memory peer (start, resume, failed turn, and JSON-wrapped provider-gate errors are covered). Failed turns surface the CLI version, raw stderr, and the human-readable inner error message for model gates like "The '' model is not supported".

Stacked on #136.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 00ff53f7-9341-4a4d-83a8-9e5236eeeaaa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 7, 2026

Copy link
Copy Markdown

Greptile Summary

The PR replaces one-shot codex exec invocations with a persistent Codex app-server JSON-RPC harness so turns can stream events and resume provider threads.

  • Adds initialization, thread start/resume, turn execution, notification reduction, and child-process lifecycle handling.
  • Routes the Codex adapter through the new runtime and adds scripted protocol tests for start, resume, completion, and provider errors.
  • The terminal event parser can return a streamed response that disagrees with the authoritative completed-turn payload.

Confidence Score: 4/5

The terminal response-selection defect should be fixed before merging because it can persist and display an answer that differs from the authoritative completed turn.

The parser replaces streamed items with the completed turn’s authoritative items but retains any previously streamed response, allowing the returned answer and item log to disagree.

Files Needing Attention: src/local-agent-runtime.ts

Important Files Changed

Filename Overview
src/local-agent-runtime.ts Implements the app-server transport and protocol lifecycle, but terminal response selection can preserve stale streamed text.
src/local-agent-runtime.test.ts Adds broad scripted protocol coverage, though streamed and terminal agent messages are always identical.
src/local-agent-adapters.ts Replaces the Codex one-shot runtime with the new app-server runtime without an independently identified adapter defect.

Sequence Diagram

sequenceDiagram
    participant D as DevSpace
    participant C as codex app-server
    D->>C: initialize
    C-->>D: initialize result
    D->>C: initialized
    alt New session
        D->>C: thread/start
    else Existing providerSessionId
        D->>C: thread/resume
    end
    C-->>D: thread id
    D->>C: turn/start
    C-->>D: item/completed notifications
    C-->>D: turn/completed (authoritative items)
    D->>D: Build finalResponse and result
    D->>C: Close stdin
Loading

Reviews (1): Last reviewed commit: "refactor(codex): drive host-installed co..." | Re-trigger Greptile

Comment on lines +148 to +154
for (const item of items) {
if (finalResponse) break;
const record = asRecord(item);
if (record?.type === "agentMessage" && typeof record.text === "string") {
finalResponse = record.text;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Terminal response remains stale

When a streamed agentMessage differs from the authoritative message in turn/completed, this loop retains the streamed text while replacing the item list with the terminal items, causing DevSpace to store and display the wrong final answer.

Suggested change
for (const item of items) {
if (finalResponse) break;
const record = asRecord(item);
if (record?.type === "agentMessage" && typeof record.text === "string") {
finalResponse = record.text;
}
}
for (const item of items) {
const record = asRecord(item);
if (record?.type === "agentMessage" && typeof record.text === "string") {
finalResponse = record.text;
}
}

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