1use anyhow::Result;
2use assistant_tool::{Tool, ToolResultOutput};
3use futures::{channel::oneshot, future::BoxFuture, stream::BoxStream};
4use gpui::SharedString;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use std::{
8 fmt::{self, Display},
9 sync::Arc,
10};
11
12#[derive(
13 Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
14)]
15pub struct ThreadId(SharedString);
16
17impl ThreadId {
18 pub fn as_str(&self) -> &str {
19 &self.0
20 }
21
22 pub fn to_string(&self) -> String {
23 self.0.to_string()
24 }
25}
26
27impl From<&str> for ThreadId {
28 fn from(value: &str) -> Self {
29 ThreadId(SharedString::from(value.to_string()))
30 }
31}
32
33impl Display for ThreadId {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 write!(f, "{}", self.0)
36 }
37}
38
39#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)]
40pub struct MessageId(pub usize);
41
42#[derive(Debug, Clone)]
43pub struct AgentThreadToolCallId(SharedString);
44
45pub enum AgentThreadResponseEvent {
46 Text(String),
47 Thinking(String),
48 ToolCallChunk {
49 id: AgentThreadToolCallId,
50 tool: Arc<dyn Tool>,
51 input: serde_json::Value,
52 },
53 ToolCall {
54 id: AgentThreadToolCallId,
55 tool: Arc<dyn Tool>,
56 input: serde_json::Value,
57 response_tx: oneshot::Sender<Result<ToolResultOutput>>,
58 },
59}
60
61pub enum AgentThreadMessage {
62 User {
63 id: MessageId,
64 chunks: Vec<AgentThreadUserMessageChunk>,
65 },
66 Assistant {
67 id: MessageId,
68 chunks: Vec<AgentThreadAssistantMessageChunk>,
69 },
70}
71
72pub enum AgentThreadUserMessageChunk {
73 Text(String),
74 // here's where we would put mentions, etc.
75}
76
77pub enum AgentThreadAssistantMessageChunk {
78 Text(String),
79 Thinking(String),
80 ToolResult {
81 id: AgentThreadToolCallId,
82 tool: Arc<dyn Tool>,
83 input: serde_json::Value,
84 output: Result<ToolResultOutput>,
85 },
86}
87
88pub struct AgentThreadResponse {
89 pub user_message_id: MessageId,
90 pub events: BoxStream<'static, Result<AgentThreadResponseEvent>>,
91}
92
93pub trait Agent {
94 fn create_thread();
95 fn list_threads();
96 fn load_thread();
97}
98
99pub trait AgentThread {
100 fn id(&self) -> ThreadId;
101 fn title(&self) -> BoxFuture<'static, Result<String>>;
102 fn summary(&self) -> BoxFuture<'static, Result<String>>;
103 fn messages(&self) -> BoxFuture<'static, Result<Vec<AgentThreadMessage>>>;
104 fn truncate(&self, message_id: MessageId) -> BoxFuture<'static, Result<()>>;
105 fn edit(
106 &self,
107 message_id: MessageId,
108 content: Vec<AgentThreadUserMessageChunk>,
109 max_iterations: usize,
110 ) -> BoxFuture<'static, Result<AgentThreadResponse>>;
111 fn send(
112 &self,
113 content: Vec<AgentThreadUserMessageChunk>,
114 max_iterations: usize,
115 ) -> BoxFuture<'static, Result<AgentThreadResponse>>;
116}