agentlib_reasoning/
utils.rs1use agentlib_core::{ModelMessage, ModelRequest, ModelResponse, ReasoningContext};
2use anyhow::{Result, anyhow};
3
4pub async fn call_model(
5 r_ctx: &mut ReasoningContext<'_>,
6 messages: Vec<ModelMessage>,
7) -> Result<ModelResponse> {
8 let tools = r_ctx.tools.list();
9 let request = ModelRequest {
10 messages,
11 tools: Some(tools),
12 };
13
14 let response = r_ctx.model.complete(request).await?;
15
16 if let Some(usage) = &response.usage {
18 r_ctx.ctx.usage.prompt_tokens += usage.prompt_tokens;
19 r_ctx.ctx.usage.completion_tokens += usage.completion_tokens;
20 r_ctx.ctx.usage.total_tokens += usage.total_tokens;
21 }
22
23 Ok(response)
24}
25
26pub async fn execute_tool_calls(
27 r_ctx: &mut ReasoningContext<'_>,
28 response: &ModelResponse,
29) -> Result<()> {
30 if let Some(tool_calls) = &response.message.tool_calls {
31 for tc in tool_calls {
32 r_ctx
33 .call_tool(&tc.name, tc.arguments.clone(), tc.id.clone())
34 .await?;
35 }
36 }
37 Ok(())
38}
39
40pub fn parse_json<T: serde::de::DeserializeOwned>(text: &str) -> Result<T> {
41 let re = regex::Regex::new(r"(?s)```(?:json)?\s*(.*?)\s*```")?;
42 let raw = if let Some(caps) = re.captures(text) {
43 caps.get(1).map_or(text, |m| m.as_str())
44 } else {
45 text
46 };
47 serde_json::from_str(raw).map_err(|e| anyhow!("Failed to parse JSON: {}", e))
48}
49
50pub fn extract_text(content: &str) -> String {
51 let re_thinking = regex::Regex::new(r"(?i)<thinking>.*?</thinking>").unwrap();
52 let re_thought = regex::Regex::new(r"(?i)<thought>.*?</thought>").unwrap();
53
54 let content = re_thinking.replace_all(content, "");
55 let content = re_thought.replace_all(&content, "");
56 content.trim().to_string()
57}