Skip to main content

claude_agent/
types.rs

1// Claude Agent — Core Types
2// Every type maps to a physical component in the clockwork brain architecture.
3
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7// ─── Prompt Caching ───────────────────────────────────────────────
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct CacheControl {
11    #[serde(rename = "type")]
12    pub cache_type: String,
13}
14
15impl CacheControl {
16    pub fn ephemeral() -> Self {
17        Self {
18            cache_type: "ephemeral".into(),
19        }
20    }
21}
22
23#[derive(Debug, Clone, Serialize)]
24pub struct SystemBlock {
25    #[serde(rename = "type")]
26    pub block_type: String,
27    pub text: String,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub cache_control: Option<CacheControl>,
30}
31
32// ─── Signal Flow ───────────────────────────────────────────────────
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct Message {
36    pub role: Role,
37    pub content: MessageContent,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(rename_all = "lowercase")]
42pub enum Role {
43    User,
44    Assistant,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum MessageContent {
50    Text(String),
51    Blocks(Vec<ContentBlock>),
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(tag = "type")]
56pub enum ContentBlock {
57    #[serde(rename = "text")]
58    Text { text: String },
59    #[serde(rename = "tool_use")]
60    ToolUse {
61        id: String,
62        name: String,
63        input: serde_json::Value,
64    },
65    #[serde(rename = "tool_result")]
66    ToolResult {
67        tool_use_id: String,
68        content: String,
69        #[serde(default)]
70        is_error: bool,
71    },
72}
73
74// ─── Layer 4: Brain Core — Model Inference ────────────────────────
75
76#[derive(Debug, Clone)]
77pub struct ModelConfig {
78    pub id: &'static str,
79    pub max_tokens: u32,
80}
81
82/// System prompt: plain string for CLI mode, structured blocks for API mode.
83#[derive(Debug, Clone, Serialize)]
84#[serde(untagged)]
85pub enum SystemPrompt {
86    Text(String),
87    Blocks(Vec<SystemBlock>),
88}
89
90#[derive(Debug, Clone, Serialize)]
91pub struct InferenceRequest {
92    pub model: String,
93    pub max_tokens: u32,
94    pub messages: Vec<Message>,
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub system: Option<SystemPrompt>,
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub tools: Option<Vec<ToolDefinition>>,
99}
100
101#[derive(Debug, Clone, Deserialize)]
102#[allow(dead_code)] // model field used by library API (AgentResponse)
103pub struct InferenceResponse {
104    pub content: Vec<ContentBlock>,
105    pub stop_reason: Option<String>,
106    pub usage: Usage,
107    pub model: String,
108    #[serde(skip)]
109    pub cli_meta: Option<CliMeta>,
110}
111
112#[derive(Debug, Clone, Deserialize, Default)]
113pub struct Usage {
114    #[serde(default)]
115    pub input_tokens: u64,
116    #[serde(default)]
117    pub output_tokens: u64,
118    #[serde(default)]
119    pub cache_read_input_tokens: u64,
120    #[serde(default)]
121    pub cache_creation_input_tokens: u64,
122}
123
124// ─── Layer 8: Brainstem — Tools ───────────────────────────────────
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct ToolDefinition {
128    pub name: String,
129    pub description: String,
130    pub input_schema: serde_json::Value,
131    #[serde(default, skip_serializing_if = "Option::is_none")]
132    pub cache_control: Option<CacheControl>,
133}
134
135impl ToolDefinition {
136    pub fn new(name: &str, description: &str, input_schema: serde_json::Value) -> Self {
137        Self {
138            name: name.into(),
139            description: description.into(),
140            input_schema,
141            cache_control: None,
142        }
143    }
144}
145
146#[derive(Debug, Clone)]
147pub struct ToolCall {
148    pub id: String,
149    pub name: String,
150    pub input: serde_json::Value,
151}
152
153#[derive(Debug, Clone)]
154pub struct ToolResult {
155    pub tool_use_id: String,
156    pub content: String,
157    pub is_error: bool,
158}
159
160// ─── Layer 3: Security Cage — Permissions ─────────────────────────
161
162#[derive(Debug, Clone)]
163pub struct PermissionRule {
164    pub pattern: String,
165}
166
167#[derive(Debug)]
168pub struct PermissionCheck {
169    pub allowed: bool,
170    pub reason: Option<String>,
171}
172
173// ─── Layer 2: Skull — Hooks ───────────────────────────────────────
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
176pub enum HookEvent {
177    // Session lifecycle
178    SessionStart,
179    SessionStop,
180    SessionResume,
181    ContextClear,
182
183    // Generic tool hooks
184    PreToolUse,
185    PostToolUse,
186    PostToolFailure,
187
188    // Granular tool hooks
189    PreBash,
190    PostBash,
191    PreFileWrite,
192    PostFileWrite,
193    PreFileRead,
194
195    // Context management
196    PreCompaction,
197    PostCompaction,
198
199    // MCP
200    PreMcpCall,
201    PostMcpCall,
202    McpError,
203
204    // Inference
205    PreInference,
206    PostInference,
207}
208
209/// Compaction strategy for context management.
210#[derive(Debug, Clone, Copy, PartialEq)]
211pub enum CompactionStrategy {
212    /// Drop old messages, keep first + last N (fast, no analysis).
213    Truncate,
214    /// Extract key information from dropped messages into a structured summary.
215    Semantic,
216}
217
218#[derive(Debug)]
219pub struct HookResult {
220    pub allow: bool,
221    pub message: Option<String>,
222}
223
224// ─── Layer 9: Root System — MCP ───────────────────────────────────
225
226#[derive(Debug, Clone, Copy, PartialEq)]
227pub enum McpDomain {
228    Specialized,
229}
230
231#[derive(Debug, Clone, Deserialize)]
232pub struct McpServerConfig {
233    pub command: String,
234    #[serde(default)]
235    pub args: Vec<String>,
236    #[serde(default)]
237    pub env: HashMap<String, String>,
238}
239
240// ─── Layer 11: Workbench — Feature Flags ──────────────────────────
241
242#[derive(Debug, Clone)]
243pub struct FeatureFlags {
244    pub summarize_tool_results: bool,
245    pub compaction_strategy: CompactionStrategy,
246    pub interactive_tool_confirm: bool,
247}
248
249impl Default for FeatureFlags {
250    fn default() -> Self {
251        Self {
252            summarize_tool_results: true,
253            compaction_strategy: CompactionStrategy::Semantic,
254            interactive_tool_confirm: false,
255        }
256    }
257}
258
259// ─── Agent Context ────────────────────────────────────────────────
260
261#[derive(Debug, Clone)]
262#[allow(dead_code)] // used by library API (Agent::new)
263pub struct AgentConfig {
264    pub memory_path: String,
265    pub hooks_dir: String,
266    pub permissions_path: String,
267    pub mcp_config_path: String,
268}
269
270impl Default for AgentConfig {
271    fn default() -> Self {
272        let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".into());
273        Self {
274            memory_path: format!("{home}/.claude-agent/memory/MEMORY.md"),
275            hooks_dir: format!("{home}/.claude-agent/hooks"),
276            permissions_path: format!("{home}/.claude-agent/permissions.json"),
277            mcp_config_path: format!("{home}/.mcp.json"),
278        }
279    }
280}
281
282#[derive(Debug, Clone, Default, Serialize)]
283pub struct AgentStats {
284    pub session_id: String,
285    pub messages_count: u64,
286    pub tool_calls: HashMap<String, u64>,
287    pub tokens_in: u64,
288    pub tokens_out: u64,
289    pub cache_read: u64,
290    pub cache_create: u64,
291    pub started_at: i64,
292    pub cost_usd: f64,
293    pub total_duration_ms: u64,
294    pub total_api_ms: u64,
295    pub total_turns: u64,
296}
297
298/// Metadata returned by the CLI backend per invocation.
299#[derive(Debug, Clone, Default)]
300pub struct CliMeta {
301    pub cost_usd: f64,
302    pub duration_ms: u64,
303    pub duration_api_ms: u64,
304    pub num_turns: u64,
305}