extern crate self as llm_toolkit;
#[cfg(feature = "agent")]
pub extern crate tracing;
pub extern crate minijinja;
#[cfg(feature = "derive")]
pub extern crate quick_xml;
#[cfg(feature = "derive")]
pub use llm_toolkit_macros::ToPrompt;
#[cfg(feature = "derive")]
pub use llm_toolkit_macros::ToPromptSet;
#[cfg(feature = "derive")]
pub use llm_toolkit_macros::ToPromptFor;
#[cfg(feature = "derive")]
pub use llm_toolkit_macros::examples_section;
#[cfg(feature = "derive")]
pub use llm_toolkit_macros::define_intent;
#[cfg(feature = "agent")]
pub use llm_toolkit_macros::Agent;
#[cfg(feature = "agent")]
pub use llm_toolkit_macros::agent;
#[cfg(feature = "agent")]
pub use llm_toolkit_macros::{TypeMarker, type_marker};
pub mod attachment;
pub mod context;
pub mod extract;
pub mod intent;
pub mod models;
pub mod multimodal;
pub mod prompt;
pub mod retrieval;
#[cfg(feature = "agent")]
pub mod observability;
#[cfg(feature = "agent")]
pub mod agent;
#[cfg(feature = "agent")]
pub mod orchestrator;
pub use attachment::{Attachment, AttachmentSchema, ToAttachments};
pub use context::{ContextProfile, Priority, TaskHealth};
pub use extract::{FlexibleExtractor, MarkdownCodeBlockExtractor};
#[cfg(feature = "agent")]
pub use intent::expandable::{
Expandable, ReActConfig, ReActError, ReActResult, RegistryError, Selectable, SelectionRegistry,
react_loop, simple_tag_selector,
};
pub use intent::frame::IntentFrame;
#[allow(deprecated)]
pub use intent::{IntentError, IntentExtractor, PromptBasedExtractor};
pub use models::{ClaudeModel, GeminiModel, Model, ModelError, OpenAIModel};
pub use multimodal::ImageData;
pub use prompt::{PromptPart, PromptSetError, ToPrompt, ToPromptFor, ToPromptSet};
pub use retrieval::Document;
#[cfg(feature = "agent")]
pub use agent::{Agent, AgentError, AnyAgent, ToExpertise};
#[cfg(feature = "agent")]
pub use agent::persona::{ContextConfig, Persona, PersonaAgent};
#[cfg(feature = "agent")]
pub use agent::retrieval::RetrievalAwareAgent;
#[cfg(feature = "agent")]
pub use agent::expertise::{
Anchor, ContextualPrompt, Expertise, KnowledgeFragment, RenderContext, WeightedFragment,
};
#[cfg(feature = "agent")]
pub use orchestrator::{
BlueprintWorkflow, Orchestrator, OrchestratorError, StrategyMap, TypeMarker,
};
use extract::ParseError;
pub fn extract_json(text: &str) -> Result<String, ParseError> {
if let Ok(content) = extract_markdown_block_with_lang(text, "json") {
return Ok(content);
}
if let Ok(content) = extract_markdown_block(text) {
let extractor = FlexibleExtractor::new();
if let Ok(json) = extractor.extract(&content) {
return Ok(json);
}
}
let extractor = FlexibleExtractor::new();
extractor.extract(text)
}
pub fn extract_markdown_block(text: &str) -> Result<String, ParseError> {
let extractor = MarkdownCodeBlockExtractor::new();
extractor.extract(text)
}
pub fn extract_markdown_block_with_lang(text: &str, lang: &str) -> Result<String, ParseError> {
let extractor = MarkdownCodeBlockExtractor::with_language(lang.to_string());
extractor.extract(text)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_json_extraction() {
let input = "Some text before {\"key\": \"value\"} and after.";
assert_eq!(extract_json(input).unwrap(), "{\"key\": \"value\"}");
}
#[test]
fn test_standard_extraction_from_tagged_content() {
let text = "<answer>{\"type\": \"success\"}</answer>";
let result = extract_json(text);
assert!(result.is_ok());
assert_eq!(result.unwrap(), "{\"type\": \"success\"}");
}
#[test]
fn test_markdown_extraction() {
let text1 = "Here is some code:\n```\nlet x = 42;\n```\nAnd some text after.";
let result1 = extract_markdown_block(text1);
assert!(result1.is_ok());
assert_eq!(result1.unwrap(), "let x = 42;");
let text2 = "Here's Rust code:\n```rust\nfn main() {
println!(\"Hello\");
}
```";
let result2 = extract_markdown_block_with_lang(text2, "rust");
assert!(result2.is_ok());
assert_eq!(result2.unwrap(), "fn main() {\n println!(\"Hello\");\n}");
let text3 = r#"\nFirst a JSON block:
```json
{"key": "value"}
```
Then a Rust block:
```rust
let data = vec![1, 2, 3];
```
"#;
let result3 = extract_markdown_block_with_lang(text3, "rust");
assert!(result3.is_ok());
assert_eq!(result3.unwrap(), "let data = vec![1, 2, 3];");
let text4 = "This text has no code blocks at all.";
let result4 = extract_markdown_block(text4);
assert!(result4.is_err());
let text5 = r#"\nLots of text before...
```python
def hello():
print("world")
return True
```
And more text after with various spacing.
"#;
let result5 = extract_markdown_block_with_lang(text5, "python");
assert!(result5.is_ok());
assert_eq!(
result5.unwrap(),
"def hello():\n print(\"world\")\n return True"
);
}
#[test]
fn test_extract_json_from_json_markdown_block() {
let text = r#"Here's the response:
```json
{"status": "success", "count": 42}
```
That's the data you requested."#;
let result = extract_json(text);
assert!(result.is_ok());
assert_eq!(result.unwrap(), r#"{"status": "success", "count": 42}"#);
}
#[test]
fn test_extract_json_from_generic_markdown_block() {
let text = r#"The output is:
```
{"result": "ok", "value": 123}
```
End of output."#;
let result = extract_json(text);
assert!(result.is_ok());
assert_eq!(result.unwrap(), r#"{"result": "ok", "value": 123}"#);
}
#[test]
fn test_extract_json_priority_json_block_over_inline() {
let text = r#"Some inline {"inline": "data"} here.
```json
{"block": "data"}
```
More text."#;
let result = extract_json(text);
assert!(result.is_ok());
assert_eq!(result.unwrap(), r#"{"block": "data"}"#);
}
#[test]
fn test_extract_json_priority_json_block_over_generic_block() {
let text = r#"First a generic block:
```
{"generic": "block"}
```
Then a JSON block:
```json
{"json": "block"}
```"#;
let result = extract_json(text);
assert!(result.is_ok());
assert_eq!(result.unwrap(), r#"{"json": "block"}"#);
}
#[test]
fn test_extract_json_fallback_from_non_json_markdown_block() {
let text = r#"Here's some code:
```
This is not JSON at all
```
But this is JSON: {"fallback": "value"}"#;
let result = extract_json(text);
assert!(result.is_ok());
assert_eq!(result.unwrap(), r#"{"fallback": "value"}"#);
}
#[test]
fn test_extract_json_from_rust_block_fallback() {
let text = r#"```rust
let x = 42;
```
The result is {"data": "inline"}"#;
let result = extract_json(text);
assert!(result.is_ok());
assert_eq!(result.unwrap(), r#"{"data": "inline"}"#);
}
#[test]
fn test_extract_json_multiline_in_markdown_block() {
let text = r#"Response:
```json
{
"name": "test",
"values": [1, 2, 3],
"nested": {
"key": "value"
}
}
```"#;
let result = extract_json(text);
assert!(result.is_ok());
let json = result.unwrap();
assert!(json.contains("\"name\": \"test\""));
assert!(json.contains("\"values\": [1, 2, 3]"));
assert!(json.contains("\"nested\""));
}
}