Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion app/src/ai/agent/api/convert_from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ pub(crate) fn convert_run_agents_harness(harness: Option<&api::Harness>) -> Opti
)
}

/// Maps the wire `computer_use_enabled` bool onto the client's tri-state
/// flag.
///
/// The generated Rust proto type has **no field presence** for this field
/// (the crate's codegen compiles the editions source as `proto3`), so an
/// unset flag and an explicit `false` both decode as `false`. Collapsing
/// that into an explicit `Some(false)` is what forced computer use off for
/// every orchestrated child whose `run_agents` call simply omitted the
/// field, bypassing the server's normal Oz default. Treat `false` as "no
/// opinion" (`None`) so the server resolves its documented default, and
/// only carry an explicit `Some(true)` through. Restoring an explicit
/// `false` end-to-end requires field presence on the wire; the rest of the
/// launch path already carries `Some(false)` faithfully once it does.
fn convert_run_agents_computer_use_enabled(computer_use_enabled: bool) -> Option<bool> {
computer_use_enabled.then_some(true)
}

fn convert_run_agents_execution_mode(
execution_mode: Option<api::run_agents::ExecutionModeOneOf>,
) -> RunAgentsExecutionMode {
Expand All @@ -100,7 +117,9 @@ fn convert_run_agents_execution_mode(
RunAgentsExecutionMode::Remote {
environment_id: remote.environment_id,
worker_host: remote.worker_host,
computer_use_enabled: remote.computer_use_enabled,
computer_use_enabled: convert_run_agents_computer_use_enabled(
remote.computer_use_enabled,
),
runner_id: remote.runner_id,
}
}
Expand Down
87 changes: 86 additions & 1 deletion app/src/ai/agent/api/convert_from_tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ai::agent::action::AskUserQuestionType;
use ai::agent::action::{AskUserQuestionType, RunAgentsExecutionMode};
use ai::skills::SkillPathOrigin;
use warp_multi_agent_api as api;

Expand Down Expand Up @@ -247,3 +247,88 @@ fn transfer_control_tool_call_converts_to_action_message() {
}
}
}

/// Builds a `run_agents` tool call whose remote block carries the given
/// `computer_use_enabled` wire value.
fn run_agents_remote_tool_call(computer_use_enabled: bool) -> api::Message {
api::Message {
fetched_memories: vec![],
id: "message".to_string(),
task_id: "task".to_string(),
server_message_data: String::new(),
citations: vec![],
message: Some(api::message::Message::ToolCall(api::message::ToolCall {
tool_call_id: "tool_call".to_string(),
tool: Some(api::message::tool_call::Tool::RunAgents(api::RunAgents {
summary: "summary".to_string(),
base_prompt: "base".to_string(),
skills: vec![],
model_id: "auto".to_string(),
harness: None,
agent_run_configs: vec![],
execution_mode: Some(api::run_agents::ExecutionModeOneOf::Remote(
api::run_agents::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled,
runner_id: String::new(),
},
)),
plan_id: String::new(),
})),
})),
request_id: "req".to_string(),
timestamp: None,
}
}

fn converted_run_agents_execution_mode(message: api::Message) -> RunAgentsExecutionMode {
let task_id = TaskId::new("task".to_string());
let converted = message
.to_client_output_message(ConversionParams {
task_id: &task_id,
current_todo_list: None,
active_code_review: None,
skill_path_origin: &SkillPathOrigin::Local,
})
.expect("run_agents conversion should succeed");
let MaybeAIAgentOutputMessage::Message(output) = converted else {
panic!("Expected run_agents tool call to produce a client action");
};
let AIAgentOutputMessageType::Action(action) = output.message else {
panic!("Expected an action message");
};
let AIAgentActionType::RunAgents(request) = action.action else {
panic!("Expected a RunAgents action");
};
request.execution_mode
}

/// Regression for REMOTE-2444: an omitted `computer_use_enabled` reaches the
/// client as the wire zero value, and must stay unspecified rather than
/// becoming an explicit disable that overrides the cloud default.
#[test]
fn run_agents_remote_without_computer_use_flag_stays_unspecified() {
assert_eq!(
converted_run_agents_execution_mode(run_agents_remote_tool_call(false)),
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: None,
runner_id: String::new(),
}
);
}

#[test]
fn run_agents_remote_with_computer_use_enabled_round_trips() {
assert_eq!(
converted_run_agents_execution_mode(run_agents_remote_tool_call(true)),
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: Some(true),
runner_id: String::new(),
}
);
}
11 changes: 8 additions & 3 deletions app/src/ai/blocklist/action_model/execute/run_agents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ use crate::ai::document::plan_publication::{
};
use crate::ai::local_harness_setup::local_harness_product_disabled_message;
use crate::ai::orchestration::{
OrchestrationConfigState, can_execute_with_auth_secret,
populate_default_auth_secret_for_execution,
OrchestrationConfigState, can_execute_with_auth_secret, effective_computer_use_enabled,
orchestration_harness, populate_default_auth_secret_for_execution,
};

/// Per-child spawn timeout. If a child agent doesn't report back within
Expand Down Expand Up @@ -357,7 +357,12 @@ impl RunAgentsExecutor {
} => RunAgentsLaunchedExecutionMode::Remote {
environment_id: environment_id.clone(),
worker_host: worker_host.clone(),
computer_use_enabled: *computer_use_enabled,
// An unspecified per-call flag resolves to the same
// default the children were launched with.
computer_use_enabled: effective_computer_use_enabled(
*computer_use_enabled,
orchestration_harness(&run_harness_type),
),
runner_id: runner_id.clone(),
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ fn remote_run_agents_action(harness_type: &str) -> AIAgentAction {
execution_mode: RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
agent_run_configs: vec![RunAgentsAgentRunConfig {
Expand Down
14 changes: 7 additions & 7 deletions app/src/ai/blocklist/block_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ fn remote_arm_propagates_skills_into_skill_references() {
&RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: true,
computer_use_enabled: Some(true),
runner_id: String::new(),
},
"oz",
Expand Down Expand Up @@ -473,7 +473,7 @@ fn remote_arm_propagates_skills_into_skill_references() {
assert_eq!(worker_host, "warp");
assert_eq!(harness_type, "oz");
assert_eq!(model_id, "auto");
assert!(computer_use_enabled);
assert_eq!(computer_use_enabled, Some(true));
assert_eq!(title, "Child");
assert_eq!(auth_secret_name, None);
assert_eq!(agent_identity_uid, None);
Expand All @@ -487,7 +487,7 @@ fn remote_arm_propagates_agent_identity_uid() {
&RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
"oz",
Expand Down Expand Up @@ -522,7 +522,7 @@ fn remote_arm_with_empty_skills_propagates_empty_vec() {
&RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
"claude",
Expand All @@ -547,7 +547,7 @@ fn remote_arm_rejects_opencode() {
&RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
"opencode",
Expand Down Expand Up @@ -600,7 +600,7 @@ fn remote_arm_propagates_claude_auth_secret_into_mode() {
&RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
"claude",
Expand All @@ -625,7 +625,7 @@ fn remote_arm_filters_whitespace_auth_secret_name_to_none() {
&RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
"codex",
Expand Down
6 changes: 3 additions & 3 deletions app/src/ai/blocklist/inline_action/orchestration_controls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ fn snapshot_execution_mode(is_local: bool) -> RunAgentsExecutionMode {
RunAgentsExecutionMode::Remote {
environment_id: String::new(),
worker_host: String::new(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
}
}
Expand Down Expand Up @@ -423,7 +423,7 @@ pub fn populate_environment_picker<A: OrchestrationControlAction, V: View>(
&RunAgentsExecutionMode::Remote {
environment_id: initial_env_id.to_string(),
worker_host: String::new(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
);
Expand Down Expand Up @@ -565,7 +565,7 @@ pub fn populate_host_picker<V: View>(
&RunAgentsExecutionMode::Remote {
environment_id: String::new(),
worker_host: initial_host.to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
);
Expand Down
39 changes: 22 additions & 17 deletions app/src/ai/blocklist/inline_action/run_agents_card_view_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ fn local_to_cloud_initializes_remote_with_empty_environment() {
};
assert_eq!(environment_id, "");
assert_eq!(worker_host, "warp");
assert!(!computer_use_enabled);
assert_eq!(
computer_use_enabled, None,
"toggling to Cloud leaves computer use unspecified so the cloud default applies"
);
}

#[test]
Expand All @@ -93,7 +96,7 @@ fn cloud_to_local_drops_environment() {
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
));
Expand Down Expand Up @@ -123,7 +126,7 @@ fn cloud_without_env_no_longer_disables_accept() {
RunAgentsExecutionMode::Remote {
environment_id: String::new(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
));
Expand All @@ -144,7 +147,7 @@ fn cloud_with_opencode_disables_accept() {
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
));
Expand Down Expand Up @@ -200,7 +203,7 @@ fn cloud_with_env_and_non_opencode_harness_allows_accept() {
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
));
Expand Down Expand Up @@ -234,7 +237,7 @@ fn set_environment_id_updates_remote() {
RunAgentsExecutionMode::Remote {
environment_id: "old".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
));
Expand All @@ -256,7 +259,7 @@ fn set_runner_id_updates_remote_and_round_trips() {
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: String::new(),
},
));
Expand All @@ -275,7 +278,7 @@ fn set_runner_id_updates_remote_and_round_trips() {
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: false,
computer_use_enabled: None,
runner_id: "runner-9".to_string(),
}
);
Expand All @@ -301,7 +304,7 @@ fn to_request_round_trips_request_fields() {
RunAgentsExecutionMode::Remote {
environment_id: "env-2".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: true,
computer_use_enabled: Some(true),
runner_id: String::new(),
},
vec![
Expand Down Expand Up @@ -535,7 +538,7 @@ mod override_from_approved_config_tests {
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: true,
computer_use_enabled: Some(true),
runner_id: String::new(),
},
));
Expand All @@ -558,7 +561,7 @@ mod override_from_approved_config_tests {
RunAgentsExecutionMode::Remote {
environment_id: "old-env".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: true,
computer_use_enabled: Some(true),
runner_id: String::new(),
},
));
Expand All @@ -574,8 +577,9 @@ mod override_from_approved_config_tests {
panic!("expected Remote");
};
assert_eq!(environment_id, "new-env", "env should come from config");
assert!(
assert_eq!(
*computer_use_enabled,
Some(true),
"computer_use_enabled should be preserved from original request"
);
}
Expand All @@ -594,9 +598,9 @@ mod override_from_approved_config_tests {
else {
panic!("expected Remote");
};
assert!(
!*computer_use_enabled,
"computer_use_enabled should default to false when original was Local"
assert_eq!(
*computer_use_enabled, None,
"computer_use_enabled should stay unspecified when original was Local"
);
}

Expand All @@ -621,7 +625,7 @@ fn local_to_cloud_idempotent_when_already_remote() {
RunAgentsExecutionMode::Remote {
environment_id: "env-1".to_string(),
worker_host: "warp".to_string(),
computer_use_enabled: true,
computer_use_enabled: Some(true),
runner_id: String::new(),
},
));
Expand All @@ -640,8 +644,9 @@ fn local_to_cloud_idempotent_when_already_remote() {
environment_id, "env-1",
"toggle to Remote when already Remote should not clobber env"
);
assert!(
assert_eq!(
computer_use_enabled,
Some(true),
"toggle to Remote when already Remote should not clobber computer_use"
);
}
Loading
Loading