1#![allow(dead_code)]
4
5use serde::{Deserialize, Serialize};
6
7use crate::task::TaskStateBase;
8use crate::types::ids::AgentId;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub enum BashTaskKind {
16 Bash,
17 Monitor,
18}
19
20pub struct LocalShellTaskState {
24 pub id: String,
26 pub task_type: String,
27 pub status: crate::task::TaskStatus,
28 pub description: String,
29 pub tool_use_id: Option<String>,
30 pub start_time: u64,
31 pub end_time: Option<u64>,
32 pub total_paused_ms: Option<u64>,
33 pub output_file: String,
34 pub output_offset: u64,
35 pub notified: bool,
36
37 pub r#type: String,
40 pub command: String,
41 pub result: Option<ShellCommandResult>,
42 pub completion_status_sent_in_attachment: bool,
43 pub shell_command: Option<Box<dyn ShellCommandTrait>>,
44 pub unregister_cleanup: Option<Box<dyn FnOnce()>>,
45 pub cleanup_timeout_id: Option<u64>,
46 pub last_reported_total_lines: usize,
48 pub is_backgrounded: Option<bool>,
51 pub agent_id: Option<AgentId>,
54 pub kind: Option<BashTaskKind>,
57}
58
59impl std::fmt::Debug for LocalShellTaskState {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct("LocalShellTaskState")
62 .field("id", &self.id)
63 .field("task_type", &self.task_type)
64 .field("status", &self.status)
65 .field("description", &self.description)
66 .field("tool_use_id", &self.tool_use_id)
67 .field("start_time", &self.start_time)
68 .field("end_time", &self.end_time)
69 .field("total_paused_ms", &self.total_paused_ms)
70 .field("output_file", &self.output_file)
71 .field("output_offset", &self.output_offset)
72 .field("notified", &self.notified)
73 .field("r#type", &self.r#type)
74 .field("command", &self.command)
75 .field("result", &self.result)
76 .field(
77 "completion_status_sent_in_attachment",
78 &self.completion_status_sent_in_attachment,
79 )
80 .field(
81 "shell_command",
82 &self
83 .shell_command
84 .as_ref()
85 .map(|_| "<dyn ShellCommandTrait>"),
86 )
87 .field(
88 "unregister_cleanup",
89 &self.unregister_cleanup.as_ref().map(|_| "<dyn FnOnce()>"),
90 )
91 .field("cleanup_timeout_id", &self.cleanup_timeout_id)
92 .field("last_reported_total_lines", &self.last_reported_total_lines)
93 .field("is_backgrounded", &self.is_backgrounded)
94 .field("agent_id", &self.agent_id)
95 .field("kind", &self.kind)
96 .finish()
97 }
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct ShellCommandResult {
103 pub code: i32,
104 pub interrupted: bool,
105}
106
107pub trait ShellCommandTrait: Send + Sync {
109 fn kill(&self);
110 fn cleanup(&self);
111}
112
113pub fn is_local_shell_task(task: &dyn std::any::Any) -> bool {
115 task.downcast_ref::<LocalShellTaskState>().is_some()
116}
117
118pub fn is_local_shell_task_from_value(task: &serde_json::Value) -> bool {
120 task.get("type").and_then(|v| v.as_str()) == Some("local_bash")
121}