Skip to main content

ai_agent/tasks/
guards.rs

1// Source: ~/claudecode/openclaudecode/src/tasks/LocalShellTask/guards.ts
2
3#![allow(dead_code)]
4
5use serde::{Deserialize, Serialize};
6
7use crate::task::TaskStateBase;
8use crate::types::ids::AgentId;
9
10/// Bash task kind - UI display variant.
11/// 'monitor' shows description instead of command, 'Monitor details' dialog title,
12/// distinct status bar pill.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub enum BashTaskKind {
16    Bash,
17    Monitor,
18}
19
20/// State for a local shell (bash) task.
21/// Extracted from LocalShellTask.tsx so non-React consumers (stopTask.ts via
22/// print.rs) don't pull React/ink into the module graph.
23pub struct LocalShellTaskState {
24    // Inherited from TaskStateBase
25    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    // LocalShellTask-specific fields
38    /// Keep as 'local_bash' for backward compatibility with persisted session state
39    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    /// Track what we last reported for computing deltas (total lines from TaskOutput)
47    pub last_reported_total_lines: usize,
48    /// Whether the task has been backgrounded
49    /// (false = foreground running, true = backgrounded)
50    pub is_backgrounded: Option<bool>,
51    /// Agent that spawned this task. Used to kill orphaned bash tasks when the
52    /// agent exits (see kill_shell_tasks_for_agent). None = main thread.
53    pub agent_id: Option<AgentId>,
54    /// UI display variant. 'monitor' shows description instead of command,
55    /// 'Monitor details' dialog title, distinct status bar pill.
56    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/// Result of a shell command execution.
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct ShellCommandResult {
103    pub code: i32,
104    pub interrupted: bool,
105}
106
107/// Trait for shell command operations (to avoid tying to a specific implementation).
108pub trait ShellCommandTrait: Send + Sync {
109    fn kill(&self);
110    fn cleanup(&self);
111}
112
113/// Type guard: check if a task is a LocalShellTask.
114pub fn is_local_shell_task(task: &dyn std::any::Any) -> bool {
115    task.downcast_ref::<LocalShellTaskState>().is_some()
116}
117
118/// Type guard: check if a task value (as a generic reference) is a LocalShellTask.
119pub 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}