Files
codex/codex-rs/app-server-client
T
stefanstokic-oai b4445f2758 [codex] add /import for external agents (#27071)
## Why

External-agent import should be discoverable and deliberate without
blocking startup or claiming the public `codex [PROMPT]` CLI namespace.
The slash command keeps the flow local to the interactive TUI and reuses
the existing app-server import API.

## What changed

- add the user-facing `/import` slash command
- detect external-agent importable items only when the command is
invoked
- run imports through the embedded local app-server
- show start and completion messages, refresh configuration, and block
duplicate imports while one is pending
- reject the flow for unsupported remote and local-daemon sessions

## Validation

- `just test -p codex-tui external_agent_config_migration` (10 passed)
- manually exercised an isolated TUI fixture with existing
external-agent setup and session data using a fresh `CODEX_HOME`
- verified picker customization, plugin and session detection, import
completion, repeated invocation, and imported-session resume context
- the broader `just test -p codex-tui` run passed 2,805 tests, with 2
unrelated guardian feature-flag failures and 4 skipped tests

## Draft follow-ups

- review whether completion messaging should remain attached to the
initiating chat if the user switches chats during an import
- review shutdown semantics for an in-progress background import

## Stack

1. [#27064](https://github.com/openai/codex/pull/27064): remove the
startup migration flow
2. [#27065](https://github.com/openai/codex/pull/27065): extract the
picker renderer
3. [#27070](https://github.com/openai/codex/pull/27070): add the
external-agent import picker UX
4. [#27071](https://github.com/openai/codex/pull/27071): expose the flow
through `/import`

**This PR is stack item 4.** Draft while the lower stack dependencies
are reviewed.
b4445f2758 ยท 2026-06-10 15:53:15 -04:00
History
..

codex-app-server-client

Shared in-process app-server client used by conversational CLI surfaces:

  • codex-exec
  • codex-tui

Purpose

This crate centralizes startup and lifecycle management for an in-process codex-app-server runtime, so CLI clients do not need to duplicate:

  • app-server bootstrap and initialize handshake
  • in-memory request/event transport wiring
  • lifecycle orchestration around caller-provided startup identity
  • graceful shutdown behavior

Startup identity

Callers pass both the app-server SessionSource and the initialize client_info.name explicitly when starting the facade.

That keeps thread metadata (for example in thread/list and thread/read) aligned with the originating runtime without baking TUI/exec-specific policy into the shared client layer.

Transport model

The in-process path uses typed channels:

  • client -> server: ClientRequest / ClientNotification
  • server -> client: InProcessServerEvent
    • ServerRequest
    • ServerNotification
    • LegacyNotification

JSON serialization is still used at external transport boundaries (stdio/websocket), but the in-process hot path is typed.

Typed requests still receive app-server responses through the JSON-RPC result envelope internally. That is intentional: the in-process path is meant to preserve app-server semantics while removing the process boundary, not to introduce a second response contract.

Bootstrap behavior

The client facade starts an already-initialized in-process runtime, but thread bootstrap still follows normal app-server flow:

  • caller sends thread/start or thread/resume
  • app-server returns the immediate typed response
  • richer session metadata may arrive later as a SessionConfigured legacy event

Surfaces such as TUI and exec may therefore need a short bootstrap phase where they reconcile startup response data with later events.

Backpressure and shutdown

  • Queues are bounded and use DEFAULT_IN_PROCESS_CHANNEL_CAPACITY by default.
  • Full queues return explicit overload behavior instead of unbounded growth.
  • shutdown() performs a bounded graceful shutdown and then aborts if timeout is exceeded.

If the client falls behind on event consumption, the worker emits InProcessServerEvent::Lagged and may reject pending server requests so approval flows do not hang indefinitely behind a saturated queue.