Skip to content

Commit 7c67079

Browse files
CSResselclaudenori-agent
authored
feat(acp): Add agent switcher to ACP CLI (#84)
Implements agent/model switching for ACP mode: - Add /agent slash command to open agent picker popup - Add agent_picker component in nori/ with SelectionViewParams - Track pending agent selection - switch happens on next prompt submission - Modify /model to show disabled options in ACP mode with redirect to /agent - Add list_available_agents() and AcpAgentInfo to ACP registry - Add AppEvent variants for SetPendingAgent, ClearPendingAgent, SubmitWithAgentSwitch - Add ACP file tracing initialization to TUI - Add E2E tests for agent switching behavior --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Nori <contact@tilework.tech>
1 parent f487fce commit 7c67079

14 files changed

Lines changed: 1027 additions & 3 deletions

File tree

codex-rs/acp/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ pub use backend::AcpBackendConfig;
1414
pub use connection::AcpConnection;
1515
pub use connection::ApprovalRequest;
1616
pub use registry::AcpAgentConfig;
17+
pub use registry::AcpAgentInfo;
1718
pub use registry::AcpProviderInfo;
1819
pub use registry::get_agent_config;
20+
pub use registry::list_available_agents;
1921
pub use tracing_setup::init_file_tracing;
2022
pub use translator::TranslatedEvent;
2123
pub use translator::translate_session_update;

codex-rs/acp/src/registry.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,49 @@
66
use anyhow::Result;
77
use std::time::Duration;
88

9+
/// Information about an available ACP agent for display in the picker
10+
#[derive(Debug, Clone, PartialEq, Eq)]
11+
pub struct AcpAgentInfo {
12+
/// Model name used to select this agent (e.g., "mock-model", "gemini-2.5-flash")
13+
pub model_name: String,
14+
/// Display name shown in the picker
15+
pub display_name: String,
16+
/// Description of the agent
17+
pub description: String,
18+
/// Provider slug for this agent
19+
pub provider_slug: String,
20+
}
21+
22+
/// Get list of all available ACP agents for the agent picker
23+
pub fn list_available_agents() -> Vec<AcpAgentInfo> {
24+
vec![
25+
AcpAgentInfo {
26+
model_name: "mock-model".to_string(),
27+
display_name: "Mock ACP".to_string(),
28+
description: "Mock agent for testing".to_string(),
29+
provider_slug: "mock-acp".to_string(),
30+
},
31+
AcpAgentInfo {
32+
model_name: "mock-model-alt".to_string(),
33+
display_name: "Mock ACP Alt".to_string(),
34+
description: "Alternate mock agent for testing".to_string(),
35+
provider_slug: "mock-acp-alt".to_string(),
36+
},
37+
AcpAgentInfo {
38+
model_name: "gemini-2.5-flash".to_string(),
39+
display_name: "Gemini 2.5 Flash".to_string(),
40+
description: "Google Gemini via ACP".to_string(),
41+
provider_slug: "gemini-acp".to_string(),
42+
},
43+
AcpAgentInfo {
44+
model_name: "claude-4.5".to_string(),
45+
display_name: "Claude 4.5".to_string(),
46+
description: "Anthropic Claude via ACP".to_string(),
47+
provider_slug: "claude-acp".to_string(),
48+
},
49+
]
50+
}
51+
952
/// Default idle timeout for ACP streaming (5 minutes)
1053
const DEFAULT_STREAM_IDLE_TIMEOUT: Duration = Duration::from_secs(300);
1154

codex-rs/tui-pty-e2e/docs.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ This delay allows the PTY subprocess time to process input and update the displa
145145
| `@/codex-rs/tui-pty-e2e/tests/input_handling.rs` | Text editing, backspace, Ctrl-C clearing, arrow key navigation with snapshot testing |
146146
| `@/codex-rs/tui-pty-e2e/tests/streaming.rs` | Prompt submission with timing delays, agent response streaming |
147147
| `@/codex-rs/tui-pty-e2e/tests/acp_mode.rs` | ACP mode startup, response flow, and approval bridging - validates TUI works with ACP wire API and mock agent; includes test for permission request display |
148-
| `@/codex-rs/tui-pty-e2e/tests/agent_switching.rs` | ACP agent subprocess lifecycle - verifies subprocess spawning, cleanup on session switch, and different agents use different processes (Linux only) |
148+
| `@/codex-rs/tui-pty-e2e/tests/agent_switching.rs` | ACP agent subprocess lifecycle and event isolation - verifies subprocess spawning, cleanup on session switch, different agents use different processes, and event filtering prevents cross-agent contamination (Linux only) |
149149
| `@/codex-rs/tui-pty-e2e/tests/live_acp.rs` | Live authenticated ACP tests for Gemini and Claude with real API connections (opt-in, marked `#[ignore]`) |
150150

151151
**Snapshot Files:**
@@ -237,7 +237,9 @@ See `@/codex-rs/mock-acp-agent/docs.md` for full list of env vars.
237237

238238
**Agent Subprocess Lifecycle Testing (`agent_switching.rs`):**
239239

240-
Linux-only tests that verify ACP subprocess lifecycle management by parsing the `.codex-acp.log` file for PID entries:
240+
Linux-only tests that verify ACP subprocess lifecycle management and event isolation:
241+
242+
*Subprocess Management Tests:*
241243
- `acp_log_path()` method on `TuiSession` returns the path to the ACP tracing log file
242244
- Tests extract PIDs from log lines matching `"ACP agent spawned (pid: Some(...))"`
243245
- Uses `/proc/{pid}` filesystem to verify process existence and zombie state
@@ -248,6 +250,11 @@ Linux-only tests that verify ACP subprocess lifecycle management by parsing the
248250
- Cleanup happens when session switches, not when individual prompt turns end
249251
- Different models (`mock-model` vs `mock-model-alt`) spawn different subprocesses
250252

253+
*Event Isolation Tests:*
254+
- `extract_agent_messages_from_log()` helper parses `Mock agent:` log entries from ACP log file
255+
- `test_agent_switch_message_flow_mock_to_mock_alt` verifies that after switching agents, the NEW agent receives and responds to prompts (catches race conditions where OLD agent events could leak)
256+
- `test_agent_switch_logs_correct_sequence` verifies the expected log sequence during agent switch: agent receives prompt, logs receipt, sends response
257+
251258
**Binary Discovery:**
252259

253260
`codex_binary_path()` locates the compiled binary:

0 commit comments

Comments
 (0)