mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Scope command approvals by execution environment (#28738)
## Why Command approval cache keys included the command and working directory, but not the execution environment. An approval for `/workspace` locally could therefore be reused for the same command and path on an executor. ## What changed - Include the selected environment ID in shell and unified-exec approval cache keys. - Carry that ID through the normal command approval request so clients can show which environment is being approved. - Expose the environment through app-server as a required nullable `environmentId` and show it in the inline TUI approval prompt. - Keep older recorded approval events compatible when the environment is absent. For example, `echo ok` in local `/workspace` and `echo ok` in executor `/workspace` now produce different approval keys and separate prompts. ## Scope This PR does not change network approvals, Guardian review actions, MCP elicitation, full-screen TUI rendering, or environment-ID validation. Remote `shell_command` execution itself remains in #28722; this PR only makes its approval key environment-aware.
This commit is contained in:
@@ -452,6 +452,7 @@ mod tests {
|
||||
item_id: "call-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: None,
|
||||
command: Some("ls".to_string()),
|
||||
@@ -791,6 +792,7 @@ mod tests {
|
||||
item_id: "call-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: None,
|
||||
command: Some("ls".to_string()),
|
||||
|
||||
@@ -615,6 +615,7 @@ mod tests {
|
||||
item_id: call_id.to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: approval_id.map(str::to_string),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: None,
|
||||
command: Some("echo hi".to_string()),
|
||||
|
||||
@@ -4690,6 +4690,7 @@ fn exec_approval_request(
|
||||
item_id: item_id.to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: approval_id.map(str::to_string),
|
||||
environment_id: None,
|
||||
reason: Some("needs approval".to_string()),
|
||||
network_approval_context: None,
|
||||
command: Some("echo hello".to_string()),
|
||||
|
||||
@@ -488,6 +488,7 @@ mod tests {
|
||||
item_id: item_id.to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: approval_id.map(str::to_string),
|
||||
environment_id: None,
|
||||
reason: Some("needs approval".to_string()),
|
||||
network_approval_context: None,
|
||||
command: Some("echo hello".to_string()),
|
||||
|
||||
@@ -226,6 +226,7 @@ impl App {
|
||||
.approval_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| params.item_id.clone()),
|
||||
environment_id: params.environment_id.clone(),
|
||||
command: params
|
||||
.command
|
||||
.as_deref()
|
||||
|
||||
@@ -26,6 +26,8 @@ pub(crate) struct ExecApprovalRequestEvent {
|
||||
pub(crate) approval_id: Option<String>,
|
||||
#[serde(default)]
|
||||
pub(crate) turn_id: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) environment_id: Option<String>,
|
||||
pub(crate) command: Vec<String>,
|
||||
pub(crate) cwd: AbsolutePathBuf,
|
||||
pub(crate) reason: Option<String>,
|
||||
|
||||
@@ -74,6 +74,7 @@ pub(crate) enum ApprovalRequest {
|
||||
thread_id: ThreadId,
|
||||
thread_label: Option<String>,
|
||||
id: String,
|
||||
environment_id: Option<String>,
|
||||
command: Vec<String>,
|
||||
reason: Option<String>,
|
||||
available_decisions: Vec<CommandExecutionApprovalDecision>,
|
||||
@@ -675,6 +676,7 @@ fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
||||
match request {
|
||||
ApprovalRequest::Exec {
|
||||
thread_label,
|
||||
environment_id,
|
||||
reason,
|
||||
command,
|
||||
network_approval_context,
|
||||
@@ -689,6 +691,13 @@ fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
||||
]));
|
||||
header.push(Line::from(""));
|
||||
}
|
||||
if let Some(environment_id) = environment_id {
|
||||
header.push(Line::from(vec![
|
||||
"Environment: ".into(),
|
||||
environment_id.clone().bold(),
|
||||
]));
|
||||
header.push(Line::from(""));
|
||||
}
|
||||
if let Some(reason) = reason {
|
||||
header.push(Line::from(vec!["Reason: ".into(), reason.clone().italic()]));
|
||||
header.push(Line::from(""));
|
||||
@@ -1220,6 +1229,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".to_string(), "hi".to_string()],
|
||||
reason: Some("reason".to_string()),
|
||||
available_decisions: vec![
|
||||
@@ -1360,6 +1370,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".to_string(), "hi".to_string()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1403,6 +1414,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["curl".to_string(), "https://example.com".to_string()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1477,6 +1489,7 @@ mod tests {
|
||||
thread_id,
|
||||
thread_label: Some("Robie [explorer]".to_string()),
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".to_string(), "hi".to_string()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1511,6 +1524,7 @@ mod tests {
|
||||
thread_id,
|
||||
thread_label: Some("Robie [explorer]".to_string()),
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".to_string(), "hi".to_string()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1549,6 +1563,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: Some("Robie [explorer]".to_string()),
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".to_string(), "hi".to_string()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1577,6 +1592,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".to_string()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1629,6 +1645,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["curl".to_string(), "https://example.com".to_string()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1668,6 +1685,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".into(),
|
||||
environment_id: None,
|
||||
command,
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -1966,6 +1984,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".into(),
|
||||
environment_id: None,
|
||||
command: vec!["cat".into(), "/tmp/readme.txt".into()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
@@ -2022,6 +2041,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".into(),
|
||||
environment_id: None,
|
||||
command: vec!["cat".into(), "/tmp/readme.txt".into()],
|
||||
reason: Some("need filesystem access".into()),
|
||||
available_decisions: vec![
|
||||
@@ -2102,6 +2122,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".into(),
|
||||
environment_id: None,
|
||||
command: vec!["curl".into(), "https://example.com".into()],
|
||||
reason: Some("network request blocked".into()),
|
||||
available_decisions: vec![
|
||||
@@ -2238,6 +2259,7 @@ mod tests {
|
||||
thread_id: ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "test".into(),
|
||||
environment_id: None,
|
||||
command: vec![
|
||||
"network-access".to_string(),
|
||||
"https://example.com:8443".to_string(),
|
||||
|
||||
@@ -1896,6 +1896,7 @@ mod tests {
|
||||
thread_id: codex_protocol::ThreadId::new(),
|
||||
thread_label: None,
|
||||
id: "1".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".into(), "ok".into()],
|
||||
reason: None,
|
||||
available_decisions: vec![
|
||||
|
||||
@@ -852,6 +852,7 @@ fn exec_approval_request_from_params(
|
||||
additional_permissions: params.additional_permissions,
|
||||
turn_id: params.turn_id,
|
||||
approval_id: params.approval_id,
|
||||
environment_id: params.environment_id,
|
||||
proposed_execpolicy_amendment: params.proposed_execpolicy_amendment,
|
||||
proposed_network_policy_amendments: params.proposed_network_policy_amendments,
|
||||
available_decisions: params.available_decisions,
|
||||
|
||||
@@ -161,6 +161,7 @@ mod tests {
|
||||
call_id: call_id.to_string(),
|
||||
approval_id: approval_id.map(str::to_string),
|
||||
turn_id: "turn".to_string(),
|
||||
environment_id: None,
|
||||
command: vec!["true".to_string()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: None,
|
||||
|
||||
@@ -13,6 +13,7 @@ async fn exec_approval_emits_proposed_command_and_decision_history() {
|
||||
call_id: "call-short".into(),
|
||||
approval_id: Some("call-short".into()),
|
||||
turn_id: "turn-short".into(),
|
||||
environment_id: Some("remote".to_string()),
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some(
|
||||
@@ -57,6 +58,7 @@ fn app_server_exec_approval_request_splits_shell_wrapped_command() {
|
||||
item_id: "item-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: None,
|
||||
command: Some(
|
||||
@@ -98,6 +100,7 @@ fn app_server_exec_approval_request_preserves_permissions_context() {
|
||||
item_id: "item-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: Some(codex_app_server_protocol::NetworkApprovalContext {
|
||||
host: "example.com".to_string(),
|
||||
@@ -157,6 +160,7 @@ async fn network_exec_approval_history_describes_session_host_allowance() {
|
||||
item_id: "item-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: Some(codex_app_server_protocol::NetworkApprovalContext {
|
||||
host: "example.com".to_string(),
|
||||
@@ -198,6 +202,7 @@ async fn network_exec_approval_history_describes_one_time_host_allowance() {
|
||||
item_id: "item-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: Some(codex_app_server_protocol::NetworkApprovalContext {
|
||||
host: "example.com".to_string(),
|
||||
@@ -239,6 +244,7 @@ async fn network_exec_approval_history_describes_canceled_host_request() {
|
||||
item_id: "item-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: Some(codex_app_server_protocol::NetworkApprovalContext {
|
||||
host: "example.com".to_string(),
|
||||
@@ -330,6 +336,7 @@ async fn exec_approval_uses_approval_id_when_present() {
|
||||
call_id: "call-parent".into(),
|
||||
approval_id: Some("approval-subcommand".into()),
|
||||
turn_id: "turn-short".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some(
|
||||
@@ -372,6 +379,7 @@ async fn exec_approval_decision_truncates_multiline_and_long_commands() {
|
||||
call_id: "call-multi".into(),
|
||||
approval_id: Some("call-multi".into()),
|
||||
turn_id: "turn-multi".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo line1\necho line2".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some(
|
||||
@@ -423,6 +431,7 @@ async fn exec_approval_decision_truncates_multiline_and_long_commands() {
|
||||
call_id: "call-long".into(),
|
||||
approval_id: Some("call-long".into()),
|
||||
turn_id: "turn-long".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), long],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: None,
|
||||
|
||||
@@ -10,6 +10,7 @@ async fn exec_approval_emits_proposed_command_and_decision_history() {
|
||||
call_id: "call-short".into(),
|
||||
approval_id: Some("call-short".into()),
|
||||
turn_id: "turn-short".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some(
|
||||
@@ -56,6 +57,7 @@ fn app_server_exec_approval_request_splits_shell_wrapped_command() {
|
||||
item_id: "item-1".to_string(),
|
||||
started_at_ms: 0,
|
||||
approval_id: Some("approval-1".to_string()),
|
||||
environment_id: None,
|
||||
reason: None,
|
||||
network_approval_context: None,
|
||||
command: Some(
|
||||
@@ -93,6 +95,7 @@ async fn exec_approval_uses_approval_id_when_present() {
|
||||
call_id: "call-parent".into(),
|
||||
approval_id: Some("approval-subcommand".into()),
|
||||
turn_id: "turn-short".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some(
|
||||
@@ -136,6 +139,7 @@ async fn exec_approval_decision_truncates_multiline_and_long_commands() {
|
||||
call_id: "call-multi".into(),
|
||||
approval_id: Some("call-multi".into()),
|
||||
turn_id: "turn-multi".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo line1\necho line2".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some(
|
||||
@@ -189,6 +193,7 @@ async fn exec_approval_decision_truncates_multiline_and_long_commands() {
|
||||
call_id: "call-long".into(),
|
||||
approval_id: Some("call-long".into()),
|
||||
turn_id: "turn-long".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), long],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: None,
|
||||
@@ -1098,6 +1103,7 @@ async fn approval_modal_exec_snapshot() -> anyhow::Result<()> {
|
||||
call_id: "call-approve-cmd".into(),
|
||||
approval_id: Some("call-approve-cmd".into()),
|
||||
turn_id: "turn-approve-cmd".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some(
|
||||
@@ -1155,6 +1161,7 @@ async fn approval_modal_exec_without_reason_snapshot() -> anyhow::Result<()> {
|
||||
call_id: "call-approve-cmd-noreason".into(),
|
||||
approval_id: Some("call-approve-cmd-noreason".into()),
|
||||
turn_id: "turn-approve-cmd-noreason".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: None,
|
||||
@@ -1201,6 +1208,7 @@ async fn approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot()
|
||||
call_id: "call-approve-cmd-multiline-trunc".into(),
|
||||
approval_id: Some("call-approve-cmd-multiline-trunc".into()),
|
||||
turn_id: "turn-approve-cmd-multiline-trunc".into(),
|
||||
environment_id: None,
|
||||
command: command.clone(),
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: None,
|
||||
|
||||
+17
-13
@@ -3,12 +3,14 @@ source: tui/src/chatwidget/tests/approval_requests.rs
|
||||
expression: "format!(\"{buf:?}\")"
|
||||
---
|
||||
Buffer {
|
||||
area: Rect { x: 0, y: 0, width: 80, height: 13 },
|
||||
area: Rect { x: 0, y: 0, width: 80, height: 15 },
|
||||
content: [
|
||||
" ",
|
||||
" ",
|
||||
" Would you like to run the following command? ",
|
||||
" ",
|
||||
" Environment: remote ",
|
||||
" ",
|
||||
" Reason: this is a test reason such as one that would be produced by the ",
|
||||
" model ",
|
||||
" ",
|
||||
@@ -23,17 +25,19 @@ Buffer {
|
||||
x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 2, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: BOLD,
|
||||
x: 46, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 10, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: ITALIC,
|
||||
x: 73, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 2, y: 5, fg: Reset, bg: Reset, underline: Reset, modifier: ITALIC,
|
||||
x: 7, y: 5, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 4, y: 7, fg: Rgb(137, 180, 250), bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 8, y: 7, fg: Rgb(205, 214, 244), bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 20, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 0, y: 9, fg: Cyan, bg: Reset, underline: Reset, modifier: BOLD,
|
||||
x: 21, y: 9, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 48, y: 10, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 51, y: 10, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 2, y: 12, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 15, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: BOLD,
|
||||
x: 21, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 10, y: 6, fg: Reset, bg: Reset, underline: Reset, modifier: ITALIC,
|
||||
x: 73, y: 6, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 2, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: ITALIC,
|
||||
x: 7, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 4, y: 9, fg: Rgb(137, 180, 250), bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 8, y: 9, fg: Rgb(205, 214, 244), bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 20, y: 9, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 0, y: 11, fg: Cyan, bg: Reset, underline: Reset, modifier: BOLD,
|
||||
x: 21, y: 11, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 48, y: 12, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
x: 51, y: 12, fg: Reset, bg: Reset, underline: Reset, modifier: NONE,
|
||||
x: 2, y: 14, fg: Reset, bg: Reset, underline: Reset, modifier: DIM,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1864,6 +1864,7 @@ async fn status_widget_and_approval_modal_snapshot() {
|
||||
call_id: "call-approve-exec".into(),
|
||||
approval_id: Some("call-approve-exec".into()),
|
||||
turn_id: "turn-approve-exec".into(),
|
||||
environment_id: None,
|
||||
command: vec!["echo".into(), "hello world".into()],
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
reason: Some(
|
||||
|
||||
@@ -13,6 +13,7 @@ async fn terminal_title_shows_action_required_while_exec_approval_is_pending() {
|
||||
call_id: "call-action-required".into(),
|
||||
approval_id: Some("call-action-required".into()),
|
||||
turn_id: "turn-action-required".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some("need confirmation".into()),
|
||||
@@ -55,6 +56,7 @@ async fn terminal_title_action_required_respects_spinner_setting() {
|
||||
call_id: "call-no-spinner".into(),
|
||||
approval_id: Some("call-no-spinner".into()),
|
||||
turn_id: "turn-no-spinner".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some("need confirmation".into()),
|
||||
@@ -83,6 +85,7 @@ async fn terminal_title_action_required_blinks_when_animations_are_enabled() {
|
||||
call_id: "call-blink".into(),
|
||||
approval_id: Some("call-blink".into()),
|
||||
turn_id: "turn-blink".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some("need confirmation".into()),
|
||||
@@ -118,6 +121,7 @@ async fn terminal_title_activity_indicators_do_not_animate_when_animations_are_d
|
||||
call_id: "call-no-animations".into(),
|
||||
approval_id: Some("call-no-animations".into()),
|
||||
turn_id: "turn-no-animations".into(),
|
||||
environment_id: None,
|
||||
command: vec!["bash".into(), "-lc".into(), "echo hello".into()],
|
||||
cwd: AbsolutePathBuf::current_dir().expect("current dir"),
|
||||
reason: Some("need confirmation".into()),
|
||||
|
||||
@@ -296,6 +296,7 @@ impl ChatWidget {
|
||||
thread_id: self.thread_id.unwrap_or_default(),
|
||||
thread_label: None,
|
||||
id: ev.effective_approval_id(),
|
||||
environment_id: ev.environment_id,
|
||||
command: ev.command,
|
||||
reason: ev.reason,
|
||||
available_decisions,
|
||||
|
||||
Reference in New Issue
Block a user