feat: Add Tool trait definition and tool_registry macro skeleton
This commit is contained in:
+103
-30
@@ -1,41 +1,114 @@
|
||||
//! worker-macros - LLMワーカー用のProcedural Macros
|
||||
//!
|
||||
//! このクレートはTools/Hooksを定義するためのマクロを提供する予定です。
|
||||
//!
|
||||
//! TODO: Tool定義マクロの実装
|
||||
//! TODO: Hook定義マクロの実装
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, ImplItem, ItemImpl};
|
||||
|
||||
/// ツール定義マクロ(未実装)
|
||||
/// `impl` ブロックに付与し、内部の `#[tool]` 属性がついたメソッドからツールを生成するマクロ。
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
/// #[tool(
|
||||
/// name = "get_weather",
|
||||
/// description = "Get weather information for a city"
|
||||
/// )]
|
||||
/// fn get_weather(city: String) -> Result<WeatherInfo, ToolError> {
|
||||
/// // ...
|
||||
/// #[tool_registry]
|
||||
/// impl MyApp {
|
||||
/// #[tool]
|
||||
/// async fn my_function(&self, arg: String) -> Result<String, Error> { ... }
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn tool_registry(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut impl_block = parse_macro_input!(item as ItemImpl);
|
||||
let self_ty = &impl_block.self_ty;
|
||||
|
||||
let mut generated_items = Vec::new();
|
||||
|
||||
for item in &mut impl_block.items {
|
||||
if let ImplItem::Fn(method) = item {
|
||||
// #[tool] 属性を探す
|
||||
let mut is_tool = false;
|
||||
let mut _description = String::new();
|
||||
|
||||
// 属性を走査してtoolがあるか確認し、削除する
|
||||
// 同時にドキュメントコメントから説明を取得
|
||||
method.attrs.retain(|attr| {
|
||||
if attr.path().is_ident("tool") {
|
||||
is_tool = true;
|
||||
false // 属性を削除
|
||||
} else if attr.path().is_ident("doc") {
|
||||
// TODO: docコメントのパース
|
||||
true
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
if is_tool {
|
||||
let sig = &method.sig;
|
||||
let method_name = &sig.ident;
|
||||
let tool_name = method_name.to_string();
|
||||
let tool_struct_name = syn::Ident::new(
|
||||
&format!("Tool_{}", method_name),
|
||||
method_name.span(),
|
||||
);
|
||||
|
||||
let factory_name = syn::Ident::new(
|
||||
&format!("{}_tool", method_name),
|
||||
method_name.span(),
|
||||
);
|
||||
|
||||
// TODO: 引数の解析とArgs構造体の生成
|
||||
// TODO: descriptionの取得
|
||||
|
||||
// 仮の実装: Contextを抱えるTool構造体を作成
|
||||
let tool_impl = quote! {
|
||||
#[derive(Clone)]
|
||||
pub struct #tool_struct_name {
|
||||
ctx: #self_ty,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl worker_types::Tool for #tool_struct_name {
|
||||
fn name(&self) -> &str {
|
||||
#tool_name
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
"TODO: description from doc comments"
|
||||
}
|
||||
|
||||
fn input_schema(&self) -> serde_json::Value {
|
||||
serde_json::json!({}) // TODO: schemars
|
||||
}
|
||||
|
||||
async fn execute(&self, input_json: &str) -> Result<String, worker_types::ToolError> {
|
||||
// TODO: Deserialize args and call check
|
||||
// self.ctx.#method_name(...)
|
||||
Ok("Not implemented yet".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl #self_ty {
|
||||
pub fn #factory_name(&self) -> #tool_struct_name {
|
||||
#tool_struct_name {
|
||||
ctx: self.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
generated_items.push(tool_impl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let expanded = quote! {
|
||||
#impl_block
|
||||
|
||||
#(#generated_items)*
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
/// マーカー属性。`tool_registry` によって処理されるため、ここでは何もしない。
|
||||
#[proc_macro_attribute]
|
||||
pub fn tool(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
// TODO: 実装
|
||||
item
|
||||
}
|
||||
|
||||
/// フック定義マクロ(未実装)
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
/// #[hook(on = "before_tool_call")]
|
||||
/// fn log_tool_call(tool_name: &str) {
|
||||
/// println!("Calling tool: {}", tool_name);
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn hook(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
// TODO: 実装
|
||||
item
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user