Struct QueryResolver

Source
pub struct QueryResolver<C: LowLevelClient> { /* private fields */ }
Expand description

Query resolver that wraps a LowLevelClient and provides all generic methods. This allows for flexible composition - you can have arrays of dyn LowLevelClient and wrap them in QueryResolver as needed.

Implementations§

Source§

impl<C: LowLevelClient> QueryResolver<C>

Source

pub fn new(client: C, config: RetryConfig) -> Self

Examples found in repository?
examples/readme_demo.rs (line 35)
32async fn main() -> Result<(), Box<dyn std::error::Error>> {
33    // Create Claude client (reads ANTHROPIC_API_KEY from environment)
34    let client = FlexibleClient::claude(ClaudeConfig::default());
35    let resolver = QueryResolver::new(client, RetryConfig::default());
36    
37    // Get 10 science quiz questions
38    let quiz: Quiz = resolver.query(
39        "Create 10 high school science quiz questions with A, B, C, D answers".to_string()
40    ).await?;
41    
42    // Administer the quiz
43    administer_quiz(quiz.questions).await;
44    Ok(())
45}
More examples
Hide additional examples
examples/schema_demo.rs (line 51)
46async fn main() -> Result<(), Box<dyn std::error::Error>> {
47    // Initialize tracing
48    tracing_subscriber::fmt::init();
49    
50    let client = MockVoid;
51    let resolver = QueryResolver::new(client, RetryConfig::default());
52    
53    // Example 1: Analysis Result
54    println!("=== Example 1: AnalysisResult Schema ===");
55    let analysis_prompt = "Analyze this code for security vulnerabilities".to_string();
56    
57    // This would normally work with a real AI client, but MockVoid just returns "{}"
58    // The important part is seeing how the schema gets generated and appended
59    match resolver.query::<AnalysisResult>(analysis_prompt).await {
60        Ok(result) => println!("Analysis result: {:?}", result),
61        Err(e) => println!("Expected error with MockVoid: {}", e),
62    }
63    
64    println!("\n=== Example 2: CodeReview Schema ===");
65    let review_prompt = "Review this Rust function for code quality".to_string();
66    
67    match resolver.query::<CodeReview>(review_prompt).await {
68        Ok(result) => println!("Review result: {:?}", result),
69        Err(e) => println!("Expected error with MockVoid: {}", e),
70    }
71    
72    // Demonstrate the schema generation directly
73    println!("\n=== Generated Schema Examples ===");
74    
75    let analysis_schema_prompt = resolver.augment_prompt_with_schema::<AnalysisResult>(
76        "Analyze this code".to_string()
77    );
78    println!("AnalysisResult schema-augmented prompt:");
79    println!("{}", analysis_schema_prompt);
80    
81    println!("\n{}", "=".repeat(80));
82    
83    let review_schema_prompt = resolver.augment_prompt_with_schema::<CodeReview>(
84        "Review this code".to_string()
85    );
86    println!("CodeReview schema-augmented prompt:");
87    println!("{}", review_schema_prompt);
88    
89    Ok(())
90}
examples/rich_schema_demo.rs (line 200)
195async fn main() -> Result<(), Box<dyn std::error::Error>> {
196    println!("🚀 Rich Schema Documentation Demo");
197    println!("This shows how to use doc comments and schemars attributes for rich AI prompts\n");
198
199    let client = MockVoid;
200    let _resolver = QueryResolver::new(client.clone(), RetryConfig::default());
201    
202    // Generate and display the enhanced schema
203    println!("=== Enhanced Analysis Result Schema ===");
204    let schema = schema_for!(EnhancedAnalysisResult);
205    let schema_json = serde_json::to_string_pretty(&schema)?;
206    println!("{}\n", schema_json);
207    
208    println!("=== Detailed Code Review Schema ===");
209    let review_schema = schema_for!(DetailedCodeReview);
210    let review_schema_json = serde_json::to_string_pretty(&review_schema)?;
211    println!("{}\n", review_schema_json);
212    
213    // Demonstrate how the prompt becomes structure-agnostic
214    println!("=== Structure-Agnostic Prompt Example ===");
215    let simple_prompt = "Analyze this code for security issues".to_string();
216    
217    let augmented_prompt = _resolver.augment_prompt_with_schema::<EnhancedAnalysisResult>(simple_prompt.clone());
218    println!("Original prompt: '{}'", simple_prompt);
219    println!("Length after schema augmentation: {} characters", augmented_prompt.len());
220    println!("Schema provides all structural details automatically!\n");
221    
222    // Show the benefits
223    println!("=== Key Benefits ===");
224    println!("✅ Rich semantic documentation embedded in struct definitions");
225    println!("✅ Automatic validation rules (ranges, examples, descriptions)");
226    println!("✅ Enum variants with clear semantic meaning");
227    println!("✅ Structure-agnostic prompts (just say what you want)");
228    println!("✅ Self-documenting code with schema generation");
229    println!("✅ AI gets comprehensive field meanings automatically");
230    
231    Ok(())
232}
examples/flexible_client_demo.rs (line 37)
14async fn main() -> Result<(), Box<dyn std::error::Error>> {
15    println!("🧪 FlexibleClient Demo");
16    println!("=================");
17    
18    // Create different client types easily
19    println!("\n1. Creating different client types:");
20    let (mock_client, _) = FlexibleClient::mock();
21    
22    println!("   ✅ Mock client: {:?}", mock_client);
23    println!("   📝 Claude/DeepSeek clients can be created with FlexibleClient::claude() / ::deepseek()");
24    
25    // Clone clients easily
26    println!("\n2. Cloning clients:");
27    let cloned_mock = mock_client.clone();
28    println!("   ✅ Cloned mock client: {:?}", cloned_mock);
29    
30    // Extract boxed clients for use with other systems
31    println!("\n3. Extract boxed clients:");
32    let _boxed_client = cloned_mock.clone_box();
33    println!("   ✅ Extracted boxed client from FlexibleClient");
34    
35    // Use with QueryResolver
36    println!("\n4. Using with QueryResolver:");
37    let resolver = QueryResolver::new(mock_client, RetryConfig::default());
38    
39    // Try a simple query (will return empty {} from mock)
40    match resolver.query::<SimpleResponse>("Hello world".to_string()).await {
41        Ok(response) => println!("   ✅ Query succeeded: {:?}", response),
42        Err(e) => println!("   ❌ Query failed (expected with mock): {}", e),
43    }
44    
45    // Demonstrate factory functions
46    println!("\n5. Factory functions for dynamic client creation:");
47    let mock_client2 = FlexibleClient::mock();
48    println!("   ✅ Created mock client: {:?}", mock_client2);
49    println!("   📝 Can also create claude/deepseek clients when API keys are available");
50    
51    println!("\n🎉 FlexibleClient demo completed!");
52    println!("    - Easy construction with FlexibleClient::mock(), ::claude(), ::deepseek()");
53    println!("    - Seamless cloning with .clone()");
54    println!("    - Extract boxed clients with .clone_inner() or .into_inner()");
55    println!("    - Works directly with QueryResolver");
56    
57    Ok(())
58}
Source

pub fn client(&self) -> &C

Get a reference to the underlying client

Source

pub fn config(&self) -> &RetryConfig

Get a reference to the retry configuration

Source

pub fn with_config(self, config: RetryConfig) -> Self

Update the retry configuration

Source

pub async fn query_raw<T>( &self, prompt: String, ) -> Result<T, QueryResolverError>

Query with retry logic and automatic JSON parsing

Source

pub async fn query<T>(&self, prompt: String) -> Result<T, QueryResolverError>

Query with automatic schema-aware prompt augmentation

Examples found in repository?
examples/readme_demo.rs (lines 38-40)
32async fn main() -> Result<(), Box<dyn std::error::Error>> {
33    // Create Claude client (reads ANTHROPIC_API_KEY from environment)
34    let client = FlexibleClient::claude(ClaudeConfig::default());
35    let resolver = QueryResolver::new(client, RetryConfig::default());
36    
37    // Get 10 science quiz questions
38    let quiz: Quiz = resolver.query(
39        "Create 10 high school science quiz questions with A, B, C, D answers".to_string()
40    ).await?;
41    
42    // Administer the quiz
43    administer_quiz(quiz.questions).await;
44    Ok(())
45}
More examples
Hide additional examples
examples/schema_demo.rs (line 59)
46async fn main() -> Result<(), Box<dyn std::error::Error>> {
47    // Initialize tracing
48    tracing_subscriber::fmt::init();
49    
50    let client = MockVoid;
51    let resolver = QueryResolver::new(client, RetryConfig::default());
52    
53    // Example 1: Analysis Result
54    println!("=== Example 1: AnalysisResult Schema ===");
55    let analysis_prompt = "Analyze this code for security vulnerabilities".to_string();
56    
57    // This would normally work with a real AI client, but MockVoid just returns "{}"
58    // The important part is seeing how the schema gets generated and appended
59    match resolver.query::<AnalysisResult>(analysis_prompt).await {
60        Ok(result) => println!("Analysis result: {:?}", result),
61        Err(e) => println!("Expected error with MockVoid: {}", e),
62    }
63    
64    println!("\n=== Example 2: CodeReview Schema ===");
65    let review_prompt = "Review this Rust function for code quality".to_string();
66    
67    match resolver.query::<CodeReview>(review_prompt).await {
68        Ok(result) => println!("Review result: {:?}", result),
69        Err(e) => println!("Expected error with MockVoid: {}", e),
70    }
71    
72    // Demonstrate the schema generation directly
73    println!("\n=== Generated Schema Examples ===");
74    
75    let analysis_schema_prompt = resolver.augment_prompt_with_schema::<AnalysisResult>(
76        "Analyze this code".to_string()
77    );
78    println!("AnalysisResult schema-augmented prompt:");
79    println!("{}", analysis_schema_prompt);
80    
81    println!("\n{}", "=".repeat(80));
82    
83    let review_schema_prompt = resolver.augment_prompt_with_schema::<CodeReview>(
84        "Review this code".to_string()
85    );
86    println!("CodeReview schema-augmented prompt:");
87    println!("{}", review_schema_prompt);
88    
89    Ok(())
90}
examples/flexible_client_demo.rs (line 40)
14async fn main() -> Result<(), Box<dyn std::error::Error>> {
15    println!("🧪 FlexibleClient Demo");
16    println!("=================");
17    
18    // Create different client types easily
19    println!("\n1. Creating different client types:");
20    let (mock_client, _) = FlexibleClient::mock();
21    
22    println!("   ✅ Mock client: {:?}", mock_client);
23    println!("   📝 Claude/DeepSeek clients can be created with FlexibleClient::claude() / ::deepseek()");
24    
25    // Clone clients easily
26    println!("\n2. Cloning clients:");
27    let cloned_mock = mock_client.clone();
28    println!("   ✅ Cloned mock client: {:?}", cloned_mock);
29    
30    // Extract boxed clients for use with other systems
31    println!("\n3. Extract boxed clients:");
32    let _boxed_client = cloned_mock.clone_box();
33    println!("   ✅ Extracted boxed client from FlexibleClient");
34    
35    // Use with QueryResolver
36    println!("\n4. Using with QueryResolver:");
37    let resolver = QueryResolver::new(mock_client, RetryConfig::default());
38    
39    // Try a simple query (will return empty {} from mock)
40    match resolver.query::<SimpleResponse>("Hello world".to_string()).await {
41        Ok(response) => println!("   ✅ Query succeeded: {:?}", response),
42        Err(e) => println!("   ❌ Query failed (expected with mock): {}", e),
43    }
44    
45    // Demonstrate factory functions
46    println!("\n5. Factory functions for dynamic client creation:");
47    let mock_client2 = FlexibleClient::mock();
48    println!("   ✅ Created mock client: {:?}", mock_client2);
49    println!("   📝 Can also create claude/deepseek clients when API keys are available");
50    
51    println!("\n🎉 FlexibleClient demo completed!");
52    println!("    - Easy construction with FlexibleClient::mock(), ::claude(), ::deepseek()");
53    println!("    - Seamless cloning with .clone()");
54    println!("    - Extract boxed clients with .clone_inner() or .into_inner()");
55    println!("    - Works directly with QueryResolver");
56    
57    Ok(())
58}
Source

pub fn augment_prompt_with_schema<T>(&self, prompt: String) -> String
where T: JsonSchema,

Generate a JSON schema for the return type and append it to the prompt

Examples found in repository?
examples/schema_demo.rs (lines 75-77)
46async fn main() -> Result<(), Box<dyn std::error::Error>> {
47    // Initialize tracing
48    tracing_subscriber::fmt::init();
49    
50    let client = MockVoid;
51    let resolver = QueryResolver::new(client, RetryConfig::default());
52    
53    // Example 1: Analysis Result
54    println!("=== Example 1: AnalysisResult Schema ===");
55    let analysis_prompt = "Analyze this code for security vulnerabilities".to_string();
56    
57    // This would normally work with a real AI client, but MockVoid just returns "{}"
58    // The important part is seeing how the schema gets generated and appended
59    match resolver.query::<AnalysisResult>(analysis_prompt).await {
60        Ok(result) => println!("Analysis result: {:?}", result),
61        Err(e) => println!("Expected error with MockVoid: {}", e),
62    }
63    
64    println!("\n=== Example 2: CodeReview Schema ===");
65    let review_prompt = "Review this Rust function for code quality".to_string();
66    
67    match resolver.query::<CodeReview>(review_prompt).await {
68        Ok(result) => println!("Review result: {:?}", result),
69        Err(e) => println!("Expected error with MockVoid: {}", e),
70    }
71    
72    // Demonstrate the schema generation directly
73    println!("\n=== Generated Schema Examples ===");
74    
75    let analysis_schema_prompt = resolver.augment_prompt_with_schema::<AnalysisResult>(
76        "Analyze this code".to_string()
77    );
78    println!("AnalysisResult schema-augmented prompt:");
79    println!("{}", analysis_schema_prompt);
80    
81    println!("\n{}", "=".repeat(80));
82    
83    let review_schema_prompt = resolver.augment_prompt_with_schema::<CodeReview>(
84        "Review this code".to_string()
85    );
86    println!("CodeReview schema-augmented prompt:");
87    println!("{}", review_schema_prompt);
88    
89    Ok(())
90}
More examples
Hide additional examples
examples/rich_schema_demo.rs (line 217)
195async fn main() -> Result<(), Box<dyn std::error::Error>> {
196    println!("🚀 Rich Schema Documentation Demo");
197    println!("This shows how to use doc comments and schemars attributes for rich AI prompts\n");
198
199    let client = MockVoid;
200    let _resolver = QueryResolver::new(client.clone(), RetryConfig::default());
201    
202    // Generate and display the enhanced schema
203    println!("=== Enhanced Analysis Result Schema ===");
204    let schema = schema_for!(EnhancedAnalysisResult);
205    let schema_json = serde_json::to_string_pretty(&schema)?;
206    println!("{}\n", schema_json);
207    
208    println!("=== Detailed Code Review Schema ===");
209    let review_schema = schema_for!(DetailedCodeReview);
210    let review_schema_json = serde_json::to_string_pretty(&review_schema)?;
211    println!("{}\n", review_schema_json);
212    
213    // Demonstrate how the prompt becomes structure-agnostic
214    println!("=== Structure-Agnostic Prompt Example ===");
215    let simple_prompt = "Analyze this code for security issues".to_string();
216    
217    let augmented_prompt = _resolver.augment_prompt_with_schema::<EnhancedAnalysisResult>(simple_prompt.clone());
218    println!("Original prompt: '{}'", simple_prompt);
219    println!("Length after schema augmentation: {} characters", augmented_prompt.len());
220    println!("Schema provides all structural details automatically!\n");
221    
222    // Show the benefits
223    println!("=== Key Benefits ===");
224    println!("✅ Rich semantic documentation embedded in struct definitions");
225    println!("✅ Automatic validation rules (ranges, examples, descriptions)");
226    println!("✅ Enum variants with clear semantic meaning");
227    println!("✅ Structure-agnostic prompts (just say what you want)");
228    println!("✅ Self-documenting code with schema generation");
229    println!("✅ AI gets comprehensive field meanings automatically");
230    
231    Ok(())
232}

Trait Implementations§

Source§

impl<C: Clone + LowLevelClient> Clone for QueryResolver<C>

Source§

fn clone(&self) -> QueryResolver<C>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<C> Freeze for QueryResolver<C>
where C: Freeze,

§

impl<C> RefUnwindSafe for QueryResolver<C>
where C: RefUnwindSafe,

§

impl<C> Send for QueryResolver<C>

§

impl<C> Sync for QueryResolver<C>

§

impl<C> Unpin for QueryResolver<C>
where C: Unpin,

§

impl<C> UnwindSafe for QueryResolver<C>
where C: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,