1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! # Tool System for Open Agent SDK
//!
//! This module provides a comprehensive tool definition system. One tool definition serves
//! both wire protocols: it converts to OpenAI's function calling shape and to Anthropic's
//! `name`/`description`/`input_schema` shape.
//!
//! ## Architecture Overview
//!
//! The tool system is built around three core concepts:
//!
//! 1. **Tool Definition** - The [`Tool`] struct contains metadata (name, description, schema)
//! and an async handler function that executes the tool's logic.
//!
//! 2. **Schema Flexibility** - Supports both simple type notation and full JSON Schema,
//! automatically converting to whichever wire format the endpoint's protocol uses.
//!
//! 3. **Async Execution** - Tools run asynchronously with a pinned, boxed future pattern
//! that enables dynamic dispatch and easy integration with async runtimes.
//!
//! ## Tool Lifecycle
//!
//! ```text
//! 1. Definition: Create tool with name, description, schema, and handler
//! 2. Registration: Add tool to agent's tool registry
//! 3. Invocation: LLM decides to call tool with specific arguments
//! 4. Execution: Handler processes arguments and returns result
//! 5. Response: Result is sent back to LLM for further processing
//! ```
//!
//! ## Schema Conversion
//!
//! The system intelligently handles multiple schema formats:
//!
//! - **Simple notation**: `{"location": "string", "units": "string"}`
//! - **Typed schema**: `{"param": {"type": "number", "description": "A value"}}`
//! - **Full JSON Schema**: Already valid JSON Schema with "type" and "properties"
//!
//! All formats are normalized to OpenAI's expected JSON Schema structure.
//!
//! ## Handler Pattern
//!
//! Tool handlers use `Pin<Box<dyn Future>>` for several critical reasons:
//!
//! - **Type Erasure**: Different async functions have different concrete types.
//! Boxing allows storing handlers with varying types in a single collection.
//!
//! - **Pinning**: Futures in Rust must be pinned to a memory location before polling.
//! Pin guarantees the future won't move, which is essential for self-referential types.
//!
//! - **Send + Sync**: These bounds ensure handlers can be safely shared across threads,
//! crucial for concurrent agent operations.
//!
//! ## Examples
//!
//! ### Creating a Simple Tool
//!
//! ```rust,no_run
//! use open_agent::{tool, Result};
//! use serde_json::json;
//!
//! // Using the builder pattern
//! let weather_tool = tool("get_weather", "Get current weather for a location")
//! .param("location", "string")
//! .param("units", "string")
//! .build(|args| async move {
//! let location = args["location"].as_str().unwrap_or("Unknown");
//! let units = args["units"].as_str().unwrap_or("celsius");
//!
//! // Simulate API call
//! Ok(json!({
//! "location": location,
//! "temperature": 22,
//! "units": units
//! }))
//! });
//! ```
//!
//! ### Creating a Tool with Complex Schema
//!
//! ```rust,no_run
//! use open_agent::Tool;
//! use serde_json::json;
//!
//! let search_tool = Tool::new(
//! "search",
//! "Search the web for information",
//! json!({
//! "query": {
//! "type": "string",
//! "description": "Search query"
//! },
//! "max_results": {
//! "type": "integer",
//! "description": "Maximum number of results",
//! "optional": true
//! }
//! }),
//! |args| Box::pin(async move {
//! // Implementation
//! Ok(json!({"results": []}))
//! })
//! );
//! ```
use crateResult;
use Value;
use Future;
use Pin;
use Arc;
include!;
include!;
include!;
include!;
include!;