Skip to main content

act_sdk_macros/
lib.rs

1mod component;
2mod tool;
3
4use proc_macro::TokenStream;
5
6/// Attribute macro for ACT component modules. Takes no arguments.
7///
8/// Transforms a module of `#[act_tool]` functions into a complete WIT component
9/// implementation (wit-bindgen world, `Guest` impl, `list_tools`/`call_tool`
10/// dispatch, plus session-provider when `#[session_open]`/`#[session_close]` are
11/// present). Component metadata and skills are embedded by `act-build pack`, not
12/// this macro.
13#[proc_macro_attribute]
14pub fn act_component(attr: TokenStream, item: TokenStream) -> TokenStream {
15    let attr_stream: proc_macro2::TokenStream = attr.into();
16    if !attr_stream.is_empty() {
17        return syn::Error::new_spanned(
18            &attr_stream,
19            "#[act_component] takes no arguments; component metadata comes from act.toml via `act-build pack`",
20        )
21        .to_compile_error()
22        .into();
23    }
24    let module = match syn::parse::<syn::ItemMod>(item) {
25        Ok(m) => m,
26        Err(e) => return e.to_compile_error().into(),
27    };
28    match component::generate(&module) {
29        Ok(tokens) => tokens.into(),
30        Err(e) => e.to_compile_error().into(),
31    }
32}
33
34/// Attribute macro for ACT tool functions.
35///
36/// When used inside an `#[act_component]` module, marks a function as a tool.
37/// The `#[act_component]` macro processes these attributes during code generation.
38///
39/// When used standalone (outside `#[act_component]`), this is a no-op pass-through.
40///
41/// # Attributes
42///
43/// - `description = "..."` (required) — Tool description
44/// - `read_only` — Mark tool as read-only
45/// - `idempotent` — Mark tool as idempotent
46/// - `destructive` — Mark tool as destructive
47/// - `streaming` — Mark tool as streaming (auto-detected if ActContext param present)
48/// - `timeout_ms = N` — Set timeout in milliseconds
49#[proc_macro_attribute]
50pub fn act_tool(_attr: TokenStream, item: TokenStream) -> TokenStream {
51    // When used standalone, pass through unchanged.
52    // When inside #[act_component], the component macro processes this.
53    item
54}
55
56/// Mark a function as `act:sessions/session-provider.open-session`.
57///
58/// Inside `#[act_component]`, the component macro picks up this annotation,
59/// generates the `session-provider` Guest impl, and derives the
60/// `get-open-session-args-schema` JSON Schema from the function's argument
61/// type via `schemars::JsonSchema`.
62///
63/// Signature: `fn open(args: T) -> ActResult<String>` (sync or async). `T`
64/// must implement `serde::Deserialize` and `schemars::JsonSchema`. The
65/// returned `String` is the session-id the host will use in subsequent
66/// capability calls.
67///
68/// Outside `#[act_component]`, this attribute is a no-op pass-through.
69#[proc_macro_attribute]
70pub fn session_open(_attr: TokenStream, item: TokenStream) -> TokenStream {
71    item
72}
73
74/// Mark a function as `act:sessions/session-provider.close-session`.
75///
76/// Signature: `fn close(session_id: String)`. Synchronous, no return value
77/// (matches the WIT close-session signature).
78///
79/// Outside `#[act_component]`, this attribute is a no-op pass-through.
80#[proc_macro_attribute]
81pub fn session_close(_attr: TokenStream, item: TokenStream) -> TokenStream {
82    item
83}