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 125 126 127 128 129 130 131 132 133 134 135
//! Provides procedural macros for the [clust](https://github.com/mochi-neko/clust).
use crate::tool::impl_tool;
use proc_macro::TokenStream;
mod check_result;
mod tool;
/// A procedural macro that generates a `clust::messages::Tool` or `clust::messages::AsyncTool`
/// implementation for the annotated function with documentation.
///
/// See also [the official guide](https://docs.anthropic.com/claude/docs/functions-external-tools).
///
/// ## Supported arguments
/// - None
/// - e.g. `fn function() -> T`
/// - A type or types that implement(s) `std::str::FromStr`.
/// - e.g.
/// - `fn function(arg1: u32) -> T`
/// - `fn function(arg1: DefinedStruct) -> T` where `DefinedStruct` implements `std::str::FromStr`.
///
/// ## Supported return values
/// - A type that implements `std::fmt::Display`.
/// - e.g.
/// - `fn function() -> u32`
/// - `fn function() -> DefinedStruct` where `DefinedStruct` implements `std::fmt::Display`.
/// - Result<T, E> where T and E implement `std::fmt::Display`.
/// - e.g.
/// - `fn function() -> Result<u32, Error>`
/// - `fn function() -> Result<DefinedStruct, Error>` where `DefinedStruct` and `Error` implement `std::fmt::Display`.
///
/// ## Supported executions
/// - Synchronous -> implement `clust::messages::Tool`
/// - e.g. `fn function() -> T`
/// - Asynchronous -> implement `clust::messages::AsyncTool`
/// - e.g. `async fn function() -> T`
///
/// ## Supported documentation formats
/// 1. Description block for the function at the top of document.
/// 2. Arguments block for the function with
/// - header: `# Arguments`, `## Arguments`, `# Parameters` or `## Parameters`.
/// - listed items: `- `arg1` - Description for the argument` or `* `arg1` - Description for the argument`.
/// 3. Other blocks are ignored.
///
/// ```rust
/// /// Description for the function.
/// ///
/// /// ## Arguments
/// /// - `arg1` - Description for the argument.
/// fn function(arg1: i32) -> i32 { arg1 }
/// ```
///
/// ## Examples
///
/// Implement a tool by `clust_tool` for a function with documentation:
///
/// ```rust
/// use clust_macros::clust_tool;
/// use std::collections::BTreeMap;
/// use std::iter::FromIterator;
/// use clust::messages::{FunctionCalls, Invoke, Tool};
///
/// /// Increments the argument by 1.
/// ///
/// /// ## Arguments
/// /// - `value` - Target value.
/// #[clust_tool]
/// fn incrementer(value: i32) -> i32 {
/// value + 1
/// }
///
/// let tool = ClustTool_incrementer {};
///
/// let description = tool.description();
///
/// let function_calls = FunctionCalls {
/// invoke: Invoke {
/// tool_name: String::from("incrementer"),
/// parameters: BTreeMap::from_iter(vec![(
/// "value".to_string(),
/// "42".to_string(),
/// )]),
/// },
/// };
///
/// let result = tool.call(function_calls).unwrap();
/// ```
///
/// Generated XML tool description from above implementation is as follows:
///
/// ```xml
/// <tool_description>
/// <tool_name>incrementer</tool_name>
/// <description>Increments the argument by 1.</description>
/// <parameters>
/// <parameter>
/// <name>value</name>
/// <type>i32</type>
/// <description>Target value.</description>
/// </parameter>
/// </parameters>
/// </tool_description>
/// ```
///
/// This tool can be called with a function calls as following XML format:
///
/// ```xml
/// <function_calls>
/// <invoke>
/// <tool_name>incrementer</tool_name>
/// <parameters>
/// <value>42</value>
/// </parameters>
/// </invoke>
/// </function_calls>
/// ```
///
/// Calling result is as following XML format:
///
/// ```xml
/// <function_results>
/// <result>
/// <tool_name>incrementer</tool_name>
/// <stdout>43</stdout>
/// </result>
/// </function_results>
/// ```
#[proc_macro_attribute]
pub fn clust_tool(
_attr: TokenStream,
item: TokenStream,
) -> TokenStream {
let item_func = syn::parse::<syn::ItemFn>(item).unwrap();
impl_tool(&item_func)
}