Skip to content

fix: migrate to ACP SDK 2.0 - #649

Merged
benbrandt merged 1 commit into
mainfrom
chore/acp-sdk-2
Oct 20, 2026
Merged

benbrandt merged 1 commit into
mainfrom
chore/acp-sdk-2

Conversation

@benbrandt

Copy link
Copy Markdown
Member

Summary

Migrate codex-acp from ACP SDK 1.5 to 2.0 while preserving the adapter's existing ACP v1, ACP v2, and AIR feature behavior.

  • Opt into the full unstable v1 and v2 SDK entrypoints consistently across implementation, tests, and examples; the SDK's default entrypoints are now stable-feature-only.
  • Replace removed legacy connection APIs in wire tests and the spawned-agent fixture with app builders and peer-context request/notify calls.
  • Use the versioned v1 unstable JSON schema export for scenario validation.
  • Remove the v2 omitted-params stream workaround. Verify the SDK handles omitted/null optional request params for both protocol versions while rejecting malformed params and missing required fields, including v2 batches.
  • Adapt v2 payload construction to the stricter discriminated-union types without changing existing snapshot outputs.
  • Keep newly added standard subagent/directed-message variants outside the adapter's emitted-update type until their dedicated migration, rather than adding unreachable runtime error cases. Existing AIR subagent updates remain unchanged.
  • Migrate the real-Codex test runner to the current connection/auth/event APIs and point the npm command at its tracked .agents path.

Most changed files contain only SDK import-path changes. No existing snapshots were updated.

Scope

This is the SDK migration only. Foreground-state/resume synchronization, structured v2 failure reporting, initial slash commands, standard system prompts, and standard subagent sessions remain separate work packages. Existing AIR behavior is preserved; the bundled Codex runtime version is unchanged.

Validation

  • npm run typecheck — passed, including examples.
  • npm test — 1,790 passed; 36 skipped.
  • npm run build — passed.
  • npm run test:integration — 4 passed against the real Codex app-server with a local mock model.
  • Standalone TypeScript check of the real-Codex runner — passed.
  • Real-Codex smoke test from an empty scratch directory — streamed sdk-upgrade-ok, with no file/tool access requested.
  • git diff --check — passed.

The full live-model E2E suite was not run. npm audit reports one pre-existing high-severity advisory in the development-only MCP test dependency; this PR does not change that dependency.

@benbrandt
benbrandt merged commit c8fd166 into main Oct 20, 2026
6 checks passed
@benbrandt
benbrandt deleted the chore/acp-sdk-2 branch October 20, 2026 10:18
benbrandt added a commit that referenced this pull request Oct 20, 2026
## Summary

Synchronize ACP v2 foreground state independently of prompt acceptance.
This PR is based directly on main after #649 merged.

- Send a current `state_update` after any requested history replay and
before every successful `session/resume` response, including
omitted/null `replayFrom`.
- Restore active runtime state on resume and serialize snapshots with
live state transitions so backpressure cannot send a stale snapshot
after newer state. Idle snapshots repeat neither completion usage nor
failure metadata.
- Report `running` when Codex accepts or reports foreground work,
including pre-insertion hooks. Prompt success still waits for the
user-message echo. Work that starts but never inserts input still ends
with an idle boundary, including transport loss before the turn-start
acknowledgment.
- Replace per-request requires_action/running brackets with
session-owned pending interactions and runnable items. Parallel work can
remain running; answering one wait does not blindly resume a
still-blocked workflow.
- Use actual runtime starts, streamed progress, and active status with
no wait flags as positive progress evidence. Nonempty Codex wait flags
count requests and are not by themselves evidence that the whole
workflow is blocked.
- Do not resume withdrawn interactions, and invalidate old waits at
idle/close so late answers cannot revive an ended turn or alter a newer
turn.
- Update the developer contract, snapshots, and focused regression
coverage. Add a real-process v2 integration test for early running,
prompt insertion, and all three resume modes.

ACP v1 behavior and the existing AIR subagent wire contract are
preserved. Standard structured failure reporting, initial commands,
system prompts, and standard subagent sessions remain separate work
packages; failure stop reasons are intentionally unchanged here.

## Specification and runtime evidence

Checked ACP specification revision `4034a8c`:
- [Current-state
synchronization](https://github.com/agentclientprotocol/agent-client-protocol/blob/4034a8cbc99bc48fd4579f70a3407b07907e0eb6/docs/protocol/v2/session-setup.mdx#L313-L329)
- [Foreground state and user-action
semantics](https://github.com/agentclientprotocol/agent-client-protocol/blob/4034a8cbc99bc48fd4579f70a3407b07907e0eb6/docs/protocol/v2/prompt-lifecycle.mdx#L843-L938)

Codex runtime status semantics checked against bundled runtime `0.160.1`
(`codex-rs/app-server/src/thread_status.rs`): wait flags count pending
interactions; active status with no wait flags implies the runtime is
running.

## Validation

- `npm run typecheck` — passed, including examples.
- `npm test` — 1,802 passed; 36 skipped.
- `npm run build` — passed.
- `npm run test:integration` — 5 passed, including the new real-process
ACP v2 test with a local mock model.
- `npm run codex-test` — live-model smoke test from an empty scratch
directory completed with `end_turn`.
- `git diff --check` — passed.

The full live-model E2E suite was not run.
benbrandt added a commit that referenced this pull request Oct 20, 2026
## Summary

Report terminal ACP v2 foreground failures through the standard `idle` /
`stopReason: "error"` shape, with an `error` object containing a code
and user-facing message. This is the next isolated package after #649
and #650, based on main.

- Carry terminal failure independently of AIR negotiation and of the
v1-shaped prompt result. Preserve v1 responses, AIR session-failure
metadata, quota, and usage.
- Cover ordinary prompted turns, local commands, compact/review
commands, implementation follow-ups, and agent-initiated turns.
- Before insertion, keep the JSON-RPC error response as well as the idle
error when foreground work ends. After insertion, keep the successful
messageId response and report the work outcome through idle.
- Preserve cancellation precedence, including runtime errors raised
while aborting. Retried model errors, individual failed tools,
unrelated-turn errors, and idle background errors do not become terminal
foreground failures.
- Close unfinished v2 tool calls before the idle failure instead of
clearing their tracker first.
- Omit opaque error data from the new standard error object; use safe
messages for process loss and unexpected internal exceptions. V2
fallback text for process loss is sanitized too.
- Keep resume snapshots free of failure details so reconnecting does not
replay a terminal incident as a new completion.

The specification checked was `4034a8c`: [v2 failure
semantics](https://github.com/agentclientprotocol/agent-client-protocol/blob/4034a8cbc99bc48fd4579f70a3407b07907e0eb6/docs/protocol/v2/prompt-lifecycle.mdx#L801-L839).

Initial commands, system prompts, and standard subagent sessions remain
separate work packages. Existing AIR subagent behavior is unchanged.

## Validation

- `npm run typecheck` — passed, including examples.
- `npm test` — 1,815 passed; 36 skipped.
- `npm run build` — passed.
- `npm run test:integration` — 5 passed against real Codex app-server
with a local mock model.
- The real-process v2 test now verifies terminal HTTP 401 -> idle/error
with code -32000, then clears the mock failure and verifies a successful
prompt and all resume modes. The mock holds the error across Codex's
authentication retry rather than accidentally returning an unrelated
error.
- Focused wire/snapshot coverage checks AIR and non-AIR failures,
pre-insertion authentication, cancellation races, failed-tool cleanup,
implementation failures, unrelated errors, and resume behavior.
- `npm run codex-test` — live-model smoke test from an empty scratch
directory completed with end_turn (backward-compatibility check).
- `git diff --check` — passed.

The full live-model E2E suite was not run. Failure scenarios use the
local model mock rather than changing real credentials or provoking
failures against an external provider.
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