1use std::collections::BTreeMap;
4use std::sync::Arc;
5use std::time::Duration;
6
7use ferrin_message::Message;
8use ferrin_spec::FinishReason;
9use ferrin_spec::JsonValue;
10use ferrin_spec::ModelId;
11use ferrin_spec::ProviderId;
12use ferrin_spec::ResponseMetadata;
13use ferrin_spec::ToolCallId;
14use ferrin_spec::ToolName;
15use ferrin_spec::Usage;
16use ferrin_spec::Warning;
17use ferrin_spec::language_model::CallOptionsRecord;
18use serde::Deserialize;
19use serde::Serialize;
20
21use crate::error::Error;
22use crate::generate_text::StepContent;
23use crate::generate_text::StepPerformance;
24use crate::generate_text::StepResult;
25use crate::generate_text::ToolErrorInfo;
26
27#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
29pub struct ModelIdentity {
30 pub provider: ProviderId,
32 pub model_id: ModelId,
34}
35
36impl ModelIdentity {
37 #[must_use]
39 pub fn new(provider: impl Into<ProviderId>, model_id: impl Into<ModelId>) -> Self {
40 Self {
41 provider: provider.into(),
42 model_id: model_id.into(),
43 }
44 }
45}
46
47#[derive(Debug, Clone, PartialEq)]
49pub struct RecordedInputs {
50 pub system: Option<crate::prompt::Instructions>,
52 pub messages: Arc<[Message]>,
54}
55
56#[derive(Debug, Clone)]
58pub struct StartEvent {
59 pub runtime_context: Option<JsonValue>,
61 pub call_id: String,
63 pub function_id: Option<String>,
65 pub model: ModelIdentity,
67 pub inputs: Option<RecordedInputs>,
69 pub metadata: BTreeMap<String, JsonValue>,
71}
72
73#[derive(Debug, Clone)]
75pub struct StepStartEvent {
76 pub runtime_context: Option<JsonValue>,
78 pub call_id: String,
80 pub step_number: u32,
82 pub model: ModelIdentity,
84 pub messages: Option<Arc<[Message]>>,
86}
87
88#[derive(Debug, Clone)]
90pub struct ModelCallStartEvent {
91 pub runtime_context: Option<JsonValue>,
93 pub call_id: String,
95 pub step_number: u32,
97 pub model: ModelIdentity,
99 pub call_options: Option<CallOptionsRecord>,
101}
102
103#[derive(Debug, Clone)]
105pub struct ModelCallEndEvent {
106 pub runtime_context: Option<JsonValue>,
108 pub call_id: String,
110 pub step_number: u32,
112 pub model: ModelIdentity,
114 pub content: Option<Vec<StepContent>>,
116 pub finish_reason: FinishReason,
118 pub usage: Usage,
120 pub response: ResponseMetadata,
122 pub performance: StepPerformance,
124 pub warnings: Vec<Warning>,
126}
127
128#[derive(Debug, Clone)]
130pub struct ToolExecutionStartEvent {
131 pub runtime_context: Option<JsonValue>,
133 pub call_id: String,
135 pub tool_call_id: ToolCallId,
137 pub tool_name: ToolName,
139 pub input: Option<JsonValue>,
141}
142
143#[derive(Debug, Clone)]
145pub struct ToolExecutionEndEvent {
146 pub runtime_context: Option<JsonValue>,
148 pub call_id: String,
150 pub tool_call_id: ToolCallId,
152 pub tool_name: ToolName,
154 pub output: Option<ToolOutcome>,
156 pub error: Option<ToolErrorInfo>,
158 pub duration: Duration,
160}
161
162#[derive(Debug, Clone, PartialEq)]
164pub struct ToolOutcome {
165 pub output: JsonValue,
167}
168
169#[derive(Debug, Clone)]
171pub struct StepEndEvent {
172 pub call_id: String,
174 pub step: Arc<StepResult>,
176}
177
178#[derive(Debug, Clone)]
180pub struct EndEvent {
181 pub runtime_context: Option<JsonValue>,
183 pub call_id: String,
185 pub steps: Arc<[StepResult]>,
187 pub total_usage: Usage,
189 pub output_recorded: Option<JsonValue>,
191}
192
193#[derive(Debug, Clone)]
195pub struct AbortEvent {
196 pub call_id: String,
198 pub steps_completed: u32,
200}
201
202#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
204#[serde(rename_all = "kebab-case")]
205#[non_exhaustive]
206pub enum ErrorPhase {
207 Prompt,
209 ModelCall,
211 ToolExecution,
213 Output,
215 Stream,
217}
218
219#[derive(Debug)]
221pub struct ErrorEvent<'a> {
222 pub call_id: &'a str,
224 pub error: &'a Error,
226 pub phase: ErrorPhase,
228}
229
230#[derive(Debug, Clone)]
232pub struct EmbedStartEvent {
233 pub call_id: String,
235 pub model: ModelIdentity,
237 pub value_count: usize,
239 pub values: Option<Vec<String>>,
241}
242
243#[derive(Debug, Clone)]
245pub struct EmbedEndEvent {
246 pub call_id: String,
248 pub embedding_count: usize,
250 pub tokens: Option<u64>,
252 pub duration: Duration,
254}
255
256#[derive(Debug, Clone)]
258pub struct RerankStartEvent {
259 pub call_id: String,
261 pub model: ModelIdentity,
263 pub document_count: usize,
265 pub query: Option<String>,
267}
268
269#[derive(Debug, Clone)]
271pub struct RerankEndEvent {
272 pub call_id: String,
274 pub ranked_count: usize,
276 pub duration: Duration,
278}