Add ACP agent backend and terminal controls

This commit is contained in:
2026-07-30 07:25:11 -05:00
parent dbfa8bcd48
commit ad24374f6d
84 changed files with 12151 additions and 157 deletions
+113 -1
View File
@@ -10,7 +10,7 @@ use crate::ai::agent::conversation::AIConversationId;
use crate::ai::agent::task::TaskId;
use crate::ai::agent::{
AIAgentAttachment, AIAgentContext, AIAgentInput, CancellationReason, ImageContext,
PassiveSuggestionTrigger, UserQueryMode,
PassiveSuggestionTrigger, RunningCommand, UserQueryMode,
};
use crate::ai::ambient_agents::AmbientAgentTaskId;
use crate::ai::blocklist::{
@@ -18,6 +18,8 @@ use crate::ai::blocklist::{
ResponseStream, ResponseStreamId,
};
use crate::ai::llms::LLMId;
use crate::persistence::model::{AcpConversationData, AgentBackend};
use crate::terminal::model::block::BlockId;
use crate::test_util::terminal::{add_window_with_terminal, initialize_app_for_terminal_view};
fn new_ambient_agent_task_id() -> AmbientAgentTaskId {
@@ -41,6 +43,116 @@ fn file_attachment(file_name: &str) -> PendingAttachment {
})
}
fn live_steering_eligibility() -> super::LiveSteeringEligibility {
super::LiveSteeringEligibility {
is_user_initiated: true,
has_shared_session_participant: false,
is_queued_prompt: false,
has_queued_query_id: false,
has_additional_attachments: false,
is_existing_task: true,
is_active_conversation: true,
has_plain_user_input: true,
has_pending_context: false,
has_action_context: false,
has_pending_passive_results: false,
}
}
#[test]
fn acp_backend_model_identity_does_not_claim_a_provider_model() {
assert_eq!(super::acp_backend_model_id(&AgentBackend::Provider), None);
assert_eq!(
super::acp_backend_model_id(&AgentBackend::Acp(AcpConversationData {
agent_id: " Codex ".to_owned(),
launch_fingerprint: "launch-123".to_owned(),
session_id: None,
})),
Some(LLMId::from("acp:codex"))
);
}
#[test]
fn live_steering_accepts_plain_input_for_the_existing_command_monitor() {
let input = super::InputQueryType::UserSubmittedQueryFromInput {
query: "Stop the command now.".to_owned(),
static_query_type: None,
running_command: Some(RunningCommand {
command: "script/soak-test".to_owned(),
block_id: BlockId::new(),
grid_contents: "elapsed: 75s".to_owned(),
cursor: String::new(),
requested_command_id: None,
is_alt_screen_active: false,
}),
};
assert!(!super::is_plain_live_steering_input(&input, false));
assert!(super::is_plain_live_steering_input(&input, true));
}
#[test]
fn running_command_monitor_identity_requires_the_same_conversation_and_block() {
App::test((), |mut app| async move {
initialize_app_for_terminal_view(&mut app);
let terminal = add_window_with_terminal(&mut app, None);
let conversation_id = AIConversationId::new();
terminal.update(&mut app, |terminal, _ctx| {
let mut terminal_model = terminal.model.lock();
terminal_model.simulate_long_running_block("sleep 100", "running");
let task_id = TaskId::new("monitor-task".to_owned());
let active_block = terminal_model.block_list_mut().active_block_mut();
active_block.set_is_agent_tagged_in(true);
active_block
.set_agent_interaction_mode_for_agent_monitored_command(&task_id, conversation_id)
.expect("tagged command should transition to agent monitoring");
let running_command = super::running_command_snapshot(&terminal_model);
assert!(super::running_command_belongs_to_monitor(
&terminal_model,
conversation_id,
&running_command,
));
assert!(!super::running_command_belongs_to_monitor(
&terminal_model,
AIConversationId::new(),
&running_command,
));
let mut other_block = running_command;
other_block.block_id = BlockId::new();
assert!(!super::running_command_belongs_to_monitor(
&terminal_model,
conversation_id,
&other_block,
));
});
});
}
#[test]
fn live_steering_retains_attachment_context_and_action_guards() {
let eligible = live_steering_eligibility();
assert!(eligible.can_attempt());
assert!(!super::LiveSteeringEligibility {
has_additional_attachments: true,
..eligible
}
.can_attempt());
assert!(!super::LiveSteeringEligibility {
has_pending_context: true,
..eligible
}
.can_attempt());
assert!(!super::LiveSteeringEligibility {
has_action_context: true,
..eligible
}
.can_attempt());
}
#[test]
fn passive_suggestions_request_params_omit_ambient_agent_task_id() {
App::test((), |mut app| async move {