Skip to main content

tool_parser/
traits.rs

1use async_trait::async_trait;
2use openai_protocol::common::Tool;
3
4use crate::{
5    errors::ParserResult,
6    types::{StreamingParseResult, ToolCall},
7};
8
9/// Core trait for all tool parsers
10#[async_trait]
11pub trait ToolParser: Send + Sync {
12    /// Parse complete tool calls from final output
13    /// Returns (remaining_normal_text, tool_calls) tuple
14    async fn parse_complete(&self, output: &str) -> ParserResult<(String, Vec<ToolCall>)>;
15
16    /// Like [`Self::parse_complete`], but with the request's tool schemas so
17    /// schema-aware parsers coerce arg values by declared type. The default
18    /// ignores `tools` and delegates to `parse_complete`.
19    async fn parse_complete_with_tools(
20        &self,
21        output: &str,
22        _tools: &[Tool],
23    ) -> ParserResult<(String, Vec<ToolCall>)> {
24        self.parse_complete(output).await
25    }
26
27    /// Parse tool calls from model output (streaming)
28    /// Parsers now maintain internal state, so self is mutable
29    ///
30    /// # Arguments
31    /// * `chunk` - New text chunk from model output
32    /// * `tools` - List of available tools for validation
33    async fn parse_incremental(
34        &mut self,
35        chunk: &str,
36        tools: &[Tool],
37    ) -> ParserResult<StreamingParseResult>;
38
39    /// Check if text contains tool calls in this parser's format
40    fn has_tool_markers(&self, text: &str) -> bool;
41
42    /// Get unstreamed tool call arguments
43    /// Returns tool call items for arguments that have been parsed but not yet streamed
44    fn get_unstreamed_tool_args(&self) -> Option<Vec<crate::types::ToolCallItem>> {
45        None
46    }
47
48    /// Take any text still buffered by the streaming parser that never became
49    /// a tool call, transferring ownership to the caller.
50    ///
51    /// Streaming consumers call this once at end of stream, alongside
52    /// [`Self::get_unstreamed_tool_args`]: text held back as a *prospective*
53    /// tool call (a bare `{` prefix, a partial start marker, or tool JSON
54    /// that never completed) must be surfaced as normal content instead of
55    /// being silently dropped — mirroring the non-streaming fallback that
56    /// returns unparsable tool text verbatim. Parsers that announced a tool
57    /// call from the buffered text return an empty string (the remaining
58    /// arguments are recovered via `get_unstreamed_tool_args`).
59    ///
60    /// The default returns an empty string (parser holds no buffered text).
61    fn take_unstreamed_normal_text(&mut self) -> String {
62        String::new()
63    }
64
65    /// Reset the parser state for reuse across requests.
66    /// This should clear all buffers and reset state to initial values.
67    fn reset(&mut self) {
68        // Default no-op implementation
69    }
70}
71
72/// Trait for partial JSON parsing
73pub trait PartialJsonParser: Send + Sync {
74    /// Parse potentially incomplete JSON
75    fn parse(&self, input: &str) -> ParserResult<(serde_json::Value, usize)>;
76
77    /// Check if JSON is complete
78    fn is_complete(&self, input: &str) -> bool;
79
80    /// Get the maximum parsing depth
81    fn max_depth(&self) -> usize;
82}