llm_worker/llm_client/
event.rs

1//! LLMクライアント層のイベント型
2//!
3//! 各LLMプロバイダからのストリーミングレスポンスを表現するイベント型。
4
5use serde::{Deserialize, Serialize};
6
7// =============================================================================
8// Core Event Types (from llm_client layer)
9// =============================================================================
10
11/// LLMからのストリーミングイベント
12///
13/// 各LLMプロバイダからのレスポンスは、この`Event`のストリームとして
14/// 統一的に処理されます。
15///
16/// # イベントの種類
17///
18/// - **メタイベント**: `Ping`, `Usage`, `Status`, `Error`
19/// - **ブロックイベント**: `BlockStart`, `BlockDelta`, `BlockStop`, `BlockAbort`
20///
21/// # ブロックのライフサイクル
22///
23/// テキストやツール呼び出しは、`BlockStart` → `BlockDelta`(複数) → `BlockStop`
24/// の順序でイベントが発生します。
25#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
26pub enum Event {
27    /// ハートビート
28    Ping(PingEvent),
29    /// トークン使用量
30    Usage(UsageEvent),
31    /// ストリームのステータス変化
32    Status(StatusEvent),
33    /// エラー発生
34    Error(ErrorEvent),
35
36    /// ブロック開始(テキスト、ツール使用等)
37    BlockStart(BlockStart),
38    /// ブロックの差分データ
39    BlockDelta(BlockDelta),
40    /// ブロック正常終了
41    BlockStop(BlockStop),
42    /// ブロック中断
43    BlockAbort(BlockAbort),
44}
45
46// =============================================================================
47// Meta Events
48// =============================================================================
49
50/// Pingイベント(ハートビート)
51#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
52pub struct PingEvent {
53    pub timestamp: Option<u64>,
54}
55
56/// 使用量イベント
57#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
58pub struct UsageEvent {
59    /// 入力トークン数
60    pub input_tokens: Option<u64>,
61    /// 出力トークン数
62    pub output_tokens: Option<u64>,
63    /// 合計トークン数
64    pub total_tokens: Option<u64>,
65    /// キャッシュ読み込みトークン数
66    pub cache_read_input_tokens: Option<u64>,
67    /// キャッシュ作成トークン数
68    pub cache_creation_input_tokens: Option<u64>,
69}
70
71/// ステータスイベント
72#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
73pub struct StatusEvent {
74    pub status: ResponseStatus,
75}
76
77/// レスポンスステータス
78#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79pub enum ResponseStatus {
80    /// ストリーム開始
81    Started,
82    /// 正常完了
83    Completed,
84    /// キャンセルされた
85    Cancelled,
86    /// エラー発生
87    Failed,
88}
89
90/// エラーイベント
91#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
92pub struct ErrorEvent {
93    pub code: Option<String>,
94    pub message: String,
95}
96
97// =============================================================================
98// Block Types
99// =============================================================================
100
101/// ブロックの種別
102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
103pub enum BlockType {
104    /// テキスト生成
105    Text,
106    /// 思考 (Claude Extended Thinking等)
107    Thinking,
108    /// ツール呼び出し
109    ToolUse,
110    /// ツール結果
111    ToolResult,
112}
113
114/// ブロック開始イベント
115#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
116pub struct BlockStart {
117    /// ブロックのインデックス
118    pub index: usize,
119    /// ブロックの種別
120    pub block_type: BlockType,
121    /// ブロック固有のメタデータ
122    pub metadata: BlockMetadata,
123}
124
125impl BlockStart {
126    pub fn block_type(&self) -> BlockType {
127        self.block_type
128    }
129}
130
131/// ブロックのメタデータ
132#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
133pub enum BlockMetadata {
134    Text,
135    Thinking,
136    ToolUse { id: String, name: String },
137    ToolResult { tool_use_id: String },
138}
139
140/// ブロックデルタイベント
141#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
142pub struct BlockDelta {
143    /// ブロックのインデックス
144    pub index: usize,
145    /// デルタの内容
146    pub delta: DeltaContent,
147}
148
149/// デルタの内容
150#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
151pub enum DeltaContent {
152    /// テキストデルタ
153    Text(String),
154    /// 思考デルタ
155    Thinking(String),
156    /// ツール引数のJSON部分文字列
157    InputJson(String),
158}
159
160impl DeltaContent {
161    /// デルタのブロック種別を取得
162    pub fn block_type(&self) -> BlockType {
163        match self {
164            DeltaContent::Text(_) => BlockType::Text,
165            DeltaContent::Thinking(_) => BlockType::Thinking,
166            DeltaContent::InputJson(_) => BlockType::ToolUse,
167        }
168    }
169}
170
171/// ブロック停止イベント
172#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
173pub struct BlockStop {
174    /// ブロックのインデックス
175    pub index: usize,
176    /// ブロックの種別
177    pub block_type: BlockType,
178    /// 停止理由
179    pub stop_reason: Option<StopReason>,
180}
181
182impl BlockStop {
183    pub fn block_type(&self) -> BlockType {
184        self.block_type
185    }
186}
187
188/// ブロック中断イベント
189#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
190pub struct BlockAbort {
191    /// ブロックのインデックス
192    pub index: usize,
193    /// ブロックの種別
194    pub block_type: BlockType,
195    /// 中断理由
196    pub reason: String,
197}
198
199impl BlockAbort {
200    pub fn block_type(&self) -> BlockType {
201        self.block_type
202    }
203}
204
205/// 停止理由
206#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
207pub enum StopReason {
208    /// 自然終了
209    EndTurn,
210    /// 最大トークン数到達
211    MaxTokens,
212    /// ストップシーケンス到達
213    StopSequence,
214    /// ツール使用
215    ToolUse,
216}
217
218// =============================================================================
219// Builder / Factory helpers
220// =============================================================================
221
222impl Event {
223    /// テキストブロック開始イベントを作成
224    pub fn text_block_start(index: usize) -> Self {
225        Event::BlockStart(BlockStart {
226            index,
227            block_type: BlockType::Text,
228            metadata: BlockMetadata::Text,
229        })
230    }
231
232    /// テキストデルタイベントを作成
233    pub fn text_delta(index: usize, text: impl Into<String>) -> Self {
234        Event::BlockDelta(BlockDelta {
235            index,
236            delta: DeltaContent::Text(text.into()),
237        })
238    }
239
240    /// テキストブロック停止イベントを作成
241    pub fn text_block_stop(index: usize, stop_reason: Option<StopReason>) -> Self {
242        Event::BlockStop(BlockStop {
243            index,
244            block_type: BlockType::Text,
245            stop_reason,
246        })
247    }
248
249    /// ツール使用ブロック開始イベントを作成
250    pub fn tool_use_start(index: usize, id: impl Into<String>, name: impl Into<String>) -> Self {
251        Event::BlockStart(BlockStart {
252            index,
253            block_type: BlockType::ToolUse,
254            metadata: BlockMetadata::ToolUse {
255                id: id.into(),
256                name: name.into(),
257            },
258        })
259    }
260
261    /// ツール引数デルタイベントを作成
262    pub fn tool_input_delta(index: usize, json: impl Into<String>) -> Self {
263        Event::BlockDelta(BlockDelta {
264            index,
265            delta: DeltaContent::InputJson(json.into()),
266        })
267    }
268
269    /// ツール使用ブロック停止イベントを作成
270    pub fn tool_use_stop(index: usize) -> Self {
271        Event::BlockStop(BlockStop {
272            index,
273            block_type: BlockType::ToolUse,
274            stop_reason: Some(StopReason::ToolUse),
275        })
276    }
277
278    /// 使用量イベントを作成
279    pub fn usage(input_tokens: u64, output_tokens: u64) -> Self {
280        Event::Usage(UsageEvent {
281            input_tokens: Some(input_tokens),
282            output_tokens: Some(output_tokens),
283            total_tokens: Some(input_tokens + output_tokens),
284            cache_read_input_tokens: None,
285            cache_creation_input_tokens: None,
286        })
287    }
288
289    /// Pingイベントを作成
290    pub fn ping() -> Self {
291        Event::Ping(PingEvent { timestamp: None })
292    }
293}