1use anyhow::Result;
8use async_trait::async_trait;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ToolDefinition {
14 pub name: String,
15 pub description: String,
16 pub parameters: serde_json::Value,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct ToolCall {
22 pub id: String,
23 pub name: String,
24 pub arguments: serde_json::Value,
25}
26
27#[derive(Debug, Clone)]
29pub struct LlmResponse {
30 pub text: String,
31 pub tool_calls: Vec<ToolCall>,
32 pub finish_reason: Option<String>,
33 pub input_tokens: usize,
34 pub output_tokens: usize,
35}
36
37#[derive(Debug, Clone)]
39pub struct LlmMessage {
40 pub role: String,
41 pub text: String,
42 pub tool_calls: Vec<ToolCall>,
43 pub tool_call_id: Option<String>,
44}
45
46impl LlmMessage {
47 pub fn user(text: String) -> Self {
49 Self {
50 role: "user".into(),
51 text,
52 tool_calls: vec![],
53 tool_call_id: None,
54 }
55 }
56 pub fn assistant(text: String) -> Self {
58 Self {
59 role: "assistant".into(),
60 text,
61 tool_calls: vec![],
62 tool_call_id: None,
63 }
64 }
65 pub fn assistant_from(resp: &LlmResponse) -> Self {
67 Self {
68 role: "assistant".into(),
69 text: resp.text.clone(),
70 tool_calls: resp.tool_calls.clone(),
71 tool_call_id: None,
72 }
73 }
74 pub fn tool_result(call_id: &str, content: &str) -> Self {
76 Self {
77 role: "tool".into(),
78 text: content.into(),
79 tool_calls: vec![],
80 tool_call_id: Some(call_id.into()),
81 }
82 }
83}
84
85#[async_trait]
87pub trait LlmProvider: Send + Sync {
88 async fn complete(
90 &self,
91 messages: Vec<LlmMessage>,
92 tools: Vec<ToolDefinition>,
93 model: &str,
94 temperature: Option<f32>,
95 ) -> Result<LlmResponse>;
96}
97
98#[async_trait]
100pub trait ToolCallRewriter: Send + Sync {
101 async fn maybe_reformat(
103 &self,
104 response: LlmResponse,
105 tools: &[ToolDefinition],
106 strict: bool,
107 ) -> Result<LlmResponse>;
108}
109
110pub trait RlmEventBus: Send + Sync {
112 fn emit_progress(&self, event: crate::RlmProgressEvent);
114 fn emit_completion(&self, event: crate::RlmCompletion);
116}