use std::path::Path;
use std::sync::Arc;
use crate::error::Result;
use crate::messaging::inbound::SendResult;
use crate::messaging::sender::MessageSender;
use crate::types::{
MessageItem, MessageItemType, ToolCallResultItem, ToolCallStartItem, ToolCallStatus,
};
use crate::util::{now_ms_i64, random::generate_run_id};
pub struct OutboundRun {
sender: Arc<MessageSender>,
to: String,
context_token: Option<String>,
run_id: String,
}
impl OutboundRun {
pub(crate) fn new(sender: Arc<MessageSender>, to: &str, context_token: Option<&str>) -> Self {
Self {
sender,
to: to.to_owned(),
context_token: context_token.map(String::from),
run_id: generate_run_id(),
}
}
#[must_use]
pub fn with_run_id(mut self, run_id: impl Into<String>) -> Self {
self.run_id = run_id.into();
self
}
pub fn run_id(&self) -> &str {
&self.run_id
}
pub fn to(&self) -> &str {
&self.to
}
pub async fn send_text(&self, text: &str) -> Result<SendResult> {
self.sender
.send_text(
&self.to,
text,
self.context_token.as_deref(),
Some(&self.run_id),
)
.await
}
pub async fn send_media(&self, file_path: &Path) -> Result<SendResult> {
self.sender
.send_media(
&self.to,
file_path,
self.context_token.as_deref(),
Some(&self.run_id),
)
.await
}
pub async fn tool_call_start(
&self,
tool_name: &str,
tool_call_id: Option<&str>,
) -> Result<SendResult> {
self.sender
.send_item(
&self.to,
build_tool_call_start_item(tool_name, tool_call_id),
self.context_token.as_deref(),
Some(&self.run_id),
)
.await
}
pub async fn tool_call_result(
&self,
tool_name: &str,
tool_call_id: Option<&str>,
status: ToolCallStatus,
) -> Result<SendResult> {
self.sender
.send_item(
&self.to,
build_tool_call_result_item(tool_name, tool_call_id, status),
self.context_token.as_deref(),
Some(&self.run_id),
)
.await
}
}
pub(crate) fn build_tool_call_start_item(
tool_name: &str,
tool_call_id: Option<&str>,
) -> MessageItem {
MessageItem {
item_type: Some(MessageItemType::ToolCallStart),
create_time_ms: Some(now_ms_i64()),
is_completed: Some(false),
tool_call_start_item: Some(ToolCallStartItem {
tool_name: Some(tool_name.to_owned()),
tool_call_id: tool_call_id.map(String::from),
}),
..Default::default()
}
}
pub(crate) fn build_tool_call_result_item(
tool_name: &str,
tool_call_id: Option<&str>,
status: ToolCallStatus,
) -> MessageItem {
MessageItem {
item_type: Some(MessageItemType::ToolCallResult),
create_time_ms: Some(now_ms_i64()),
is_completed: Some(true),
tool_call_result_item: Some(ToolCallResultItem {
tool_name: Some(tool_name.to_owned()),
tool_call_id: tool_call_id.map(String::from),
status: Some(status.as_str().to_owned()),
}),
..Default::default()
}
}