vtcode_core/llm/provider.rs
1//! Universal LLM provider abstraction with API-specific role handling
2//!
3//! This module provides a unified interface for different LLM providers (OpenAI, Anthropic, Gemini)
4//! while properly handling their specific requirements for message roles and tool calling.
5//!
6//! ## Message Role Mapping
7//!
8//! Different LLM providers have varying support for message roles, especially for tool calling:
9//!
10//! ### OpenAI API
11//! - **Full Support**: `system`, `user`, `assistant`, `tool`
12//! - **Tool Messages**: Must include `tool_call_id` to reference the original tool call
13//! - **Tool Calls**: Only `assistant` messages can contain `tool_calls`
14//!
15//! ### Anthropic API
16//! - **Standard Roles**: `user`, `assistant`
17//! - **System Messages**: Can be hoisted to system parameter or treated as user messages
18//! - **Tool Responses**: Converted to `user` messages (no separate tool role)
19//! - **Tool Choice**: Supports `auto`, `any`, `tool`, `none` modes
20//!
21//! ### Gemini API
22//! - **Conversation Roles**: Only `user` and `model` (not `assistant`)
23//! - **System Messages**: Handled separately as `systemInstruction` parameter
24//! - **Tool Responses**: Converted to `user` messages with `functionResponse` format
25//! - **Function Calls**: Uses `functionCall` in `model` messages
26//!
27//! ## Best Practices
28//!
29//! 1. Always use `MessageRole::tool_response()` constructor for tool responses
30//! 2. Validate messages using `validate_for_provider()` before sending
31//! 3. Use appropriate role mapping methods for each provider
32//! 4. Handle provider-specific constraints (e.g., Gemini's system instruction requirement)
33//!
34//! ## Example Usage
35//!
36//! ```rust
37//! use vtcode_core::llm::provider::{Message, MessageRole};
38//!
39//! // Create a proper tool response message
40//! let tool_response = Message::tool_response(
41//! "call_123".to_string(),
42//! "Tool execution completed successfully".to_string()
43//! );
44//!
45//! // Validate for specific provider
46//! tool_response.validate_for_provider("openai").unwrap();
47//! ```
48
49mod call;
50mod message;
51mod provider_trait;
52mod request;
53mod response;
54mod responses_continuation;
55#[cfg(test)]
56mod tests;
57mod tool;
58
59pub use call::{FunctionCall, ToolCall};
60pub use message::{AssistantPhase, ContentPart, Message, MessageContent, MessageRole};
61pub use provider_trait::{
62 LLMError, LLMErrorMetadata, LLMProvider, ProviderCapabilities, get_cached_capabilities,
63};
64pub use request::{
65 AnthropicOptionalStringOverride, AnthropicOptionalU32Override, AnthropicRequestOverrides,
66 AnthropicThinkingDisplayOverride, AnthropicThinkingModeOverride, CodingAgentSettings,
67 LLMRequest, ParallelToolConfig, PromptCacheProfile, ResponsesCompactionOptions,
68 SpecificFunctionChoice, SpecificToolChoice, ToolChoice,
69};
70pub use response::{
71 BorrowedLLMStream, FinishReason, LLMNormalizedStream, LLMResponse, LLMStream, LLMStreamEvent,
72 NormalizedStreamEvent, Usage,
73};
74pub use responses_continuation::{
75 PreparedResponsesRequest, ResponsesContinuationState, prepare_openai_responses_request,
76 prepare_responses_continuation_request, responses_continuation_key,
77 supports_responses_chaining, uses_incremental_responses_history,
78};
79pub use tool::{
80 FunctionDefinition, GrammarDefinition, ShellToolDefinition, ToolDefinition, ToolSearchAlgorithm,
81};