(
output: String,
pending_calls: HashMap<usize, StreamingToolCall>,
_stop_reason: Option<String>,
)
| 1906 | } |
| 1907 | |
| 1908 | fn finalize_llm_turn( |
| 1909 | output: String, |
| 1910 | pending_calls: HashMap<usize, StreamingToolCall>, |
| 1911 | _stop_reason: Option<String>, |
| 1912 | ) -> AppResult<LLMTurn> { |
| 1913 | let mut sorted: Vec<(usize, StreamingToolCall)> = pending_calls.into_iter().collect(); |
| 1914 | sorted.sort_by_key(|(index, _)| *index); |
| 1915 | |
| 1916 | let mut tool_calls = Vec::new(); |
| 1917 | for (_, call) in sorted { |
| 1918 | if call.id.is_empty() || call.name.is_empty() { |
| 1919 | continue; |
| 1920 | } |
| 1921 | |
| 1922 | let input = if call.arguments.trim().is_empty() { |
| 1923 | json!({}) |
| 1924 | } else { |
| 1925 | serde_json::from_str(&call.arguments).map_err(|error| { |
| 1926 | AppError::Json(format!( |
| 1927 | "Failed to parse tool arguments for '{}': {}. Raw: {}", |
| 1928 | call.name, error, call.arguments |
| 1929 | )) |
| 1930 | })? |
| 1931 | }; |
| 1932 | |
| 1933 | tool_calls.push(ParsedToolCall { |
| 1934 | id: call.id, |
| 1935 | name: call.name, |
| 1936 | input, |
| 1937 | }); |
| 1938 | } |
| 1939 | |
| 1940 | Ok(LLMTurn { |
| 1941 | text: output, |
| 1942 | tool_calls, |
| 1943 | }) |
| 1944 | } |
| 1945 | |
| 1946 | fn to_openai_messages(messages: &[ConversationMessage]) -> Vec<Value> { |
| 1947 | messages |
no outgoing calls
no test coverage detected