tiny_loop_macros/lib.rs
1mod tool;
2
3use crate::tool::tool_impl;
4use proc_macro::TokenStream;
5use quote::quote;
6
7/// Transforms a function or method into a tool with generated args struct and `ToolArgs` implementation.
8///
9/// # Usage
10///
11/// ## Transform a Function
12///
13/// ```ignore
14/// use tiny_loop::{Agent, tool::tool, llm::OpenAIProvider};
15///
16/// #[tool]
17/// async fn get_weather(
18/// /// City name
19/// city: String,
20/// ) -> String {
21/// format!("Weather in {}: Sunny", city)
22/// }
23///
24/// let agent = Agent::new(OpenAIProvider::new())
25/// .tool(get_weather);
26/// ```
27///
28/// ## Transform Methods
29///
30/// For methods, use `.bind()`:
31///
32/// ```ignore
33/// #[derive(Clone)]
34/// struct Database;
35///
36/// #[tool]
37/// impl Database {
38/// /// Query the database
39/// async fn query(
40/// self,
41/// /// SQL query
42/// sql: String,
43/// ) -> String {
44/// format!("Results for: {}", sql)
45/// }
46/// }
47///
48/// let db = Database;
49/// let agent = Agent::new(OpenAIProvider::new())
50/// .bind(db, Database::query);
51/// ```
52///
53/// # Macro Expansion
54///
55/// ## Transform a Function
56///
57/// Input function:
58/// ```ignore
59/// /// Fetch a URL.
60/// #[tool]
61/// pub async fn fetch(
62/// /// URL to fetch
63/// url: String,
64/// ) -> String {
65/// todo!()
66/// }
67/// ```
68///
69/// Expands to:
70/// ```ignore
71/// /// Arguments for the `fetch` tool.
72/// #[derive(serde::Deserialize, schemars::JsonSchema)]
73/// pub struct FetchArgs {
74/// /// URL to fetch
75/// pub url: String,
76/// }
77///
78/// impl tiny_loop::tool::ToolArgs for FetchArgs {
79/// const TOOL_NAME: &'static str = "fetch";
80/// const TOOL_DESCRIPTION: &'static str = "Fetch a URL.";
81/// }
82///
83/// /// Fetch a URL.
84/// pub async fn fetch(args: FetchArgs) -> String {
85/// let FetchArgs { url } = args;
86/// todo!()
87/// }
88/// ```
89///
90/// ## Transform Methods
91///
92/// Input method:
93/// ```ignore
94/// impl Database {
95/// /// Query database
96/// #[tool]
97/// pub async fn query(
98/// self,
99/// /// SQL query
100/// sql: String,
101/// ) -> String {
102/// todo!()
103/// }
104/// }
105/// ```
106///
107/// Expands to:
108/// ```ignore
109/// /// Arguments for the `query` tool.
110/// #[derive(serde::Deserialize, schemars::JsonSchema)]
111/// pub struct QueryArgs {
112/// /// SQL query
113/// pub sql: String,
114/// }
115///
116/// impl tiny_loop::tool::ToolArgs for QueryArgs {
117/// const TOOL_NAME: &'static str = "query";
118/// const TOOL_DESCRIPTION: &'static str = "Query database";
119/// }
120///
121/// impl Database {
122/// /// Query database
123/// pub async fn query(self, args: QueryArgs) -> String {
124/// let QueryArgs { sql } = args;
125/// todo!()
126/// }
127/// }
128/// ```
129#[proc_macro_attribute]
130pub fn tool(_attr: TokenStream, item: TokenStream) -> TokenStream {
131 tool_impl(item, quote!(tiny_loop::tool::ToolArgs))
132}
133
134/// Same as `#[tool]` but uses internal `ToolArgs` path for use within the `tiny-loop` crate.
135#[doc(hidden)]
136#[proc_macro_attribute]
137pub fn tool_internal(_attr: TokenStream, item: TokenStream) -> TokenStream {
138 tool_impl(item, quote!(crate::tool::ToolArgs))
139}