starweaver_runtime/
direct.rs1use serde::{Deserialize, Serialize};
4use starweaver_core::{ConversationId, RunId, TraceContext};
5use starweaver_model::{
6 ModelAdapter, ModelError, ModelMessage, ModelRequestContext, ModelRequestParameters,
7 ModelResponse, ModelResponseStreamEvent, ModelSettings, ToolCallPart, ToolReturnPart,
8};
9use starweaver_tools::{ToolContext, ToolRegistry};
10
11#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
13pub struct DirectModelRequest {
14 #[serde(default, skip_serializing_if = "Vec::is_empty")]
16 pub messages: Vec<ModelMessage>,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub settings: Option<ModelSettings>,
20 #[serde(default)]
22 pub params: ModelRequestParameters,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub run_id: Option<RunId>,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub conversation_id: Option<ConversationId>,
29 #[serde(default, skip_serializing_if = "TraceContext::is_empty")]
31 pub trace_context: TraceContext,
32}
33
34impl DirectModelRequest {
35 #[must_use]
37 pub fn new(messages: Vec<ModelMessage>) -> Self {
38 Self {
39 messages,
40 ..Self::default()
41 }
42 }
43
44 #[must_use]
46 pub fn with_settings(mut self, settings: ModelSettings) -> Self {
47 self.settings = Some(settings);
48 self
49 }
50
51 #[must_use]
53 pub fn with_params(mut self, params: ModelRequestParameters) -> Self {
54 self.params = params;
55 self
56 }
57
58 #[must_use]
60 pub fn with_ids(mut self, run_id: RunId, conversation_id: ConversationId) -> Self {
61 self.run_id = Some(run_id);
62 self.conversation_id = Some(conversation_id);
63 self
64 }
65
66 #[must_use]
68 pub fn with_trace_context(mut self, trace_context: TraceContext) -> Self {
69 self.trace_context = trace_context;
70 self
71 }
72
73 fn context(&self) -> ModelRequestContext {
74 ModelRequestContext::new(
75 self.run_id.clone().unwrap_or_default(),
76 self.conversation_id.clone().unwrap_or_default(),
77 )
78 .with_trace_context(self.trace_context.clone())
79 }
80}
81
82pub async fn model_request(
88 model: &dyn ModelAdapter,
89 request: DirectModelRequest,
90) -> Result<ModelResponse, ModelError> {
91 let context = request.context();
92 model
93 .request_stream_final(request.messages, request.settings, request.params, context)
94 .await
95}
96
97pub async fn model_request_stream(
103 model: &dyn ModelAdapter,
104 request: DirectModelRequest,
105) -> Result<Vec<ModelResponseStreamEvent>, ModelError> {
106 let context = request.context();
107 model
108 .request_stream(request.messages, request.settings, request.params, context)
109 .await
110}
111
112pub async fn tool_call(
114 tools: &ToolRegistry,
115 context: ToolContext,
116 call: &ToolCallPart,
117) -> ToolReturnPart {
118 tools.execute_call(context, call).await
119}