Skip to main content

vtcode_llm/providers/
common.rs

1//! Shared provider helpers, grouped by responsibility behind stable imports.
2
3mod chat;
4mod http;
5mod prompt_cache;
6mod reasoning;
7mod request;
8mod streaming;
9mod token_count;
10
11pub(crate) use chat::{
12    convert_usage_to_llm_types, map_finish_reason_common, parse_chat_request_openai_format,
13    parse_response_openai_format, parse_usage_openai_format, serialize_message_content_openai,
14    serialize_message_content_openai_for_model, serialize_message_content_openai_for_role,
15    serialize_messages_openai_format, serialize_tools_openai_format,
16};
17pub(crate) use http::{
18    PROVIDER_ERROR_BODY_MAX_BYTES, chat_completions_url, extract_header, override_base_url, parse_json_response,
19    read_provider_error_body, send_chat_completions,
20};
21pub use prompt_cache::forward_prompt_cache_with_state;
22pub(crate) use prompt_cache::{extract_prompt_cache_settings, extract_prompt_cache_settings_default};
23pub(crate) use reasoning::{
24    append_normalized_reasoning_detail_items, assistant_interleaved_history_text, is_interleaved_thinking_model,
25    is_minimax_m2_model, normalize_reasoning_detail_object, normalize_reasoning_detail_objects,
26    preserve_interleaved_content_in_reasoning_details, serialize_reasoning_detail_values,
27};
28pub use reasoning::{
29    extract_reasoning_text_from_detail_values, extract_reasoning_text_from_serialized_details,
30    make_anthropic_thinking_config,
31};
32pub(crate) use request::{
33    collect_history_system_directives, ensure_model, float_to_json_number, make_default_request,
34    merge_system_prompt_with_history_directives, parse_client_prompt_common, resolve_model, sampling_param_f64,
35    validate_request_common, validate_supported_models,
36};
37pub(crate) use streaming::{TaskAbortGuard, spawn_openai_compatible_stream};
38pub use token_count::{
39    execute_token_count_request, parse_prompt_tokens_from_count_response, strip_generation_controls_for_token_count,
40};
41
42/// Implements the `LLMClient` trait for an OpenAI-compatible provider.
43/// All providers share the same pattern: create a default request, delegate to `LLMProvider::generate`.
44///
45/// Helpers are named by an absolute `crate::` path (not `super::`) so the
46/// macro stays correct in any invoking module; see
47/// `docs/development/rust-macro-hygiene.md`.
48macro_rules! impl_llm_client {
49    ($provider:ty) => {
50        #[async_trait::async_trait]
51        impl crate::client::LLMClient for $provider {
52            async fn generate(
53                &mut self,
54                prompt: &str,
55            ) -> Result<crate::provider::LLMResponse, crate::provider::LLMError> {
56                let request = crate::providers::common::make_default_request(prompt, &self.model);
57                Ok(<$provider as crate::provider::LLMProvider>::generate(self, request).await?)
58            }
59
60            fn model_id(&self) -> &str {
61                &self.model
62            }
63        }
64    };
65}
66
67pub(crate) use impl_llm_client;
68
69#[cfg(test)]
70mod tests;