infinity_provider_protocol/completion.rs
1//! Completion request, response streaming, and error types.
2
3use std::pin::Pin;
4
5use futures_util::Stream;
6use serde::{Deserialize, Serialize};
7
8use crate::message::{Message, Reasoning, ToolCall};
9
10/// A request to stream one completion from a model.
11///
12/// This is the entire API surface providers must support; anything
13/// provider-specific (thinking configuration, beta flags, ...) travels in
14/// `additional_params` or is applied by the provider itself.
15#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
16pub struct CompletionRequest {
17 /// The system prompt.
18 pub preamble: Option<String>,
19 /// The conversation so far, ending with the content to complete.
20 pub chat_history: Vec<Message>,
21 /// Definitions of the tools available to the model.
22 pub tools: Vec<ToolDefinition>,
23 /// Maximum number of output tokens. `None` uses the provider's default.
24 pub max_tokens: Option<u64>,
25 /// Extra provider-specific request parameters, merged into the request
26 /// by the provider.
27 pub additional_params: Option<serde_json::Value>,
28}
29
30/// Definition of one tool the model may call.
31#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
32pub struct ToolDefinition {
33 pub name: String,
34 pub description: String,
35 /// JSON schema of the tool's arguments.
36 pub parameters: serde_json::Value,
37}
38
39/// Token usage reported by a provider for one completion.
40#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
41pub struct Usage {
42 /// The number of input ("prompt") tokens used in a given request.
43 #[serde(default)]
44 pub input_tokens: u64,
45 /// The number of output ("completion") tokens used in a given request.
46 #[serde(default)]
47 pub output_tokens: u64,
48 /// Stored separately as some providers only report one number.
49 #[serde(default)]
50 pub total_tokens: u64,
51 /// The number of cached input tokens (from prompt caching). 0 if not
52 /// reported by the provider.
53 #[serde(default)]
54 pub cached_input_tokens: u64,
55}
56
57/// Error invoking a completion model.
58#[derive(Debug, thiserror::Error)]
59pub enum CompletionError {
60 /// Error building the completion request.
61 #[error("RequestError: {0}")]
62 RequestError(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
63
64 /// Error parsing the completion response.
65 #[error("ResponseError: {0}")]
66 ResponseError(String),
67
68 /// Error returned by the completion model provider.
69 #[error("ProviderError: {0}")]
70 ProviderError(String),
71
72 /// JSON (de)serialization error.
73 #[error("JsonError: {0}")]
74 JsonError(#[from] serde_json::Error),
75}
76
77/// One streamed item of a completion response.
78///
79/// Deltas stream incremental UI-facing content; the non-delta variants
80/// (`ToolCall`, `Reasoning`) carry the complete block to be recorded in
81/// history. A well-formed stream ends with `Final` (though providers may
82/// terminate without one, e.g. on network errors).
83#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
84pub enum StreamChunk {
85 /// A chunk of assistant text.
86 Text(String),
87 /// A complete tool call (all arguments accumulated).
88 ToolCall(ToolCall),
89 /// An incremental piece of an in-progress tool call.
90 ToolCallDelta {
91 /// Provider-supplied tool call id.
92 id: String,
93 content: ToolCallDeltaContent,
94 },
95 /// A complete reasoning block.
96 Reasoning(Reasoning),
97 /// A chunk of reasoning text.
98 ReasoningDelta { id: Option<String>, text: String },
99 /// The final chunk, carrying the completion's token usage (if the
100 /// provider reports it).
101 Final(FinalResponse),
102}
103
104/// The content of a [`StreamChunk::ToolCallDelta`].
105#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
106pub enum ToolCallDeltaContent {
107 /// The name of the tool being called (start of the call).
108 Name(String),
109 /// A fragment of the call's JSON arguments.
110 Delta(String),
111}
112
113/// Payload of [`StreamChunk::Final`].
114#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
115pub struct FinalResponse {
116 pub usage: Option<Usage>,
117}
118
119/// The streaming response returned by a model invocation.
120pub type ModelStream = Pin<Box<dyn Stream<Item = Result<StreamChunk, CompletionError>> + Send>>;