Skip to main content

hh_cli/session/
types.rs

1use crate::core::{Message, ToolCall};
2use serde::{Deserialize, Serialize};
3
4fn default_subagent_status_running() -> SubAgentLifecycleStatus {
5    SubAgentLifecycleStatus::Running
6}
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
9#[serde(rename_all = "snake_case")]
10pub enum SubAgentLifecycleStatus {
11    Pending,
12    Running,
13    Completed,
14    Failed,
15    Cancelled,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
19#[serde(rename_all = "snake_case")]
20pub enum SubAgentFailureReason {
21    ToolError,
22    ApprovalDenied,
23    RuntimeError,
24    InterruptedByRestart,
25    Unknown,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
29#[serde(tag = "event", rename_all = "snake_case")]
30pub enum SessionEvent {
31    Message {
32        id: String,
33        #[serde(flatten)]
34        message: Message,
35    },
36    ToolCall {
37        #[serde(flatten)]
38        call: ToolCall,
39    },
40    ToolResult {
41        id: String,
42        is_error: bool,
43        output: String,
44        #[serde(default, skip_serializing_if = "Option::is_none")]
45        result: Option<crate::tool::ToolResult>,
46    },
47    Approval {
48        id: String,
49        tool_name: String,
50        approved: bool,
51    },
52    Thinking {
53        id: String,
54        content: String,
55    },
56    Compact {
57        id: String,
58        summary: String,
59    },
60    SubAgentStart {
61        id: String,
62        #[serde(default, skip_serializing_if = "Option::is_none")]
63        task_id: Option<String>,
64        #[serde(default, skip_serializing_if = "Option::is_none")]
65        name: Option<String>,
66        #[serde(default, skip_serializing_if = "Option::is_none")]
67        parent_id: Option<String>,
68        #[serde(default, skip_serializing_if = "Option::is_none")]
69        parent_session_id: Option<String>,
70        #[serde(default, skip_serializing_if = "Option::is_none")]
71        agent_name: Option<String>,
72        #[serde(default, skip_serializing_if = "Option::is_none")]
73        session_id: Option<String>,
74        #[serde(default = "default_subagent_status_running")]
75        status: SubAgentLifecycleStatus,
76        #[serde(default)]
77        created_at: u64,
78        #[serde(default)]
79        updated_at: u64,
80        prompt: String,
81        depth: usize,
82    },
83    SubAgentProgress {
84        id: String,
85        #[serde(default, skip_serializing_if = "Option::is_none")]
86        task_id: Option<String>,
87        #[serde(default)]
88        seq: u64,
89        content: String,
90    },
91    SubAgentResult {
92        id: String,
93        #[serde(default, skip_serializing_if = "Option::is_none")]
94        task_id: Option<String>,
95        #[serde(default = "default_subagent_status_running")]
96        status: SubAgentLifecycleStatus,
97        #[serde(default, skip_serializing_if = "Option::is_none")]
98        summary: Option<String>,
99        #[serde(default, skip_serializing_if = "Option::is_none")]
100        failure_reason: Option<SubAgentFailureReason>,
101        is_error: bool,
102        output: String,
103    },
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct SessionMetadata {
108    pub id: String,
109    pub title: String,
110    pub created_at: u64,      // Unix timestamp
111    pub last_updated_at: u64, // Unix timestamp
112    #[serde(default, skip_serializing_if = "Option::is_none")]
113    pub parent_session_id: Option<String>,
114}