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
//! Procedural-macro companion to `loopctl`'s [`Tool`] trait.
//!
//! [`Tool`] here is a derive macro: apply it to a
//! `Deserialize` struct describing the tool's input and it generates the
//! `impl loopctl::tool::Tool` block — the name, description, JSON-Schema
//! built statically from the struct's fields, and a `call` that
//! deserializes the incoming `Value` into the struct and dispatches to
//! an inherent `async fn run` handler you supply.
//!
//! # Attribute Grammar
//!
//! On the struct (container attributes):
//!
//! ```text
//! #[tool(
//! name = "snake_case_name", // default: snake_cased struct ident
//! description = "one-liner", // default: struct doc comment
//! read_only, // override is_read_only() -> true
//! concurrency_safe, // override is_concurrency_safe() -> true
//! system_prompt = "extra hint", // override system_prompt()
//! handler = "my_run", // default: "run"
//! allow_extra // omit additionalProperties: false
//! )]
//! ```
//!
//! On each field:
//!
//! ```text
//! #[tool(
//! name = "json_key", // default: Rust field name (or serde's rename)
//! description = "field help", // default: field doc comment
//! skip, // exclude from schema + required
//! default // omit from required, keep in properties
//! )]
//! ```
//!
//! `#[serde(rename = "…")]` and `#[serde(rename_all = "…")]` are
//! honored for schema naming, mirroring what serde deserializes with;
//! `#[tool(name = "…")]` takes precedence over both.
//!
//! Re-exported from the `loopctl` crate behind its `derive` feature, so
//! the usual spelling is:
//!
//! ```rust,ignore
//! use loopctl::Tool; // brings both the trait and the derive into scope
//! ```
//!
//! See the `Tool` trait docs in `loopctl` for the attribute grammar.
//!
//! [`Tool`]: https://docs.rs/loopctl/latest/loopctl/tool/trait.Tool.html
use TokenStream;
/// Derive `loopctl::tool::Tool` for a struct.
///
/// Generates all four required methods from the struct's shape: the
/// name (container override or the `snake_cased` identifier), the
/// description (container override or the struct's doc comment — one
/// of the two is required), the JSON Schema built statically from the
/// fields, and a `call` that deserializes the incoming `Value` and
/// dispatches to a handler. The struct must implement
/// `serde::Deserialize` (add `#[derive(serde::Deserialize)]`
/// alongside) and provide an inherent
/// `async fn run(&self, input: Self, ctx: &ToolContext)` returning
/// `Result<ToolOutput, ToolError>`; rename the handler with
/// `#[tool(handler = "…")]`. Tools with dynamic schemas or
/// unmappable field types fall back to a manual `impl`.