docs: Translate ja -> en
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
//! llm-worker-macros - Tool生成用手続きマクロ
|
||||
//! llm-worker-macros - Procedural macros for Tool generation
|
||||
//!
|
||||
//! `#[tool_registry]` と `#[tool]` マクロを提供し、
|
||||
//! ユーザー定義のメソッドから `Tool` トレイト実装を自動生成する。
|
||||
//! Provides `#[tool_registry]` and `#[tool]` macros to
|
||||
//! automatically generate `Tool` trait implementations from user-defined methods.
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
@@ -9,22 +9,22 @@ use syn::{
|
||||
Attribute, FnArg, ImplItem, ItemImpl, Lit, Meta, Pat, ReturnType, Type, parse_macro_input,
|
||||
};
|
||||
|
||||
/// `impl` ブロックに付与し、内部の `#[tool]` 属性がついたメソッドからツールを生成するマクロ。
|
||||
/// Macro applied to an `impl` block that generates tools from methods marked with `#[tool]`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
/// #[tool_registry]
|
||||
/// impl MyApp {
|
||||
/// /// ユーザー情報を取得する
|
||||
/// /// 指定されたIDのユーザーをDBから検索します。
|
||||
/// /// Get user information
|
||||
/// /// Retrieves a user from the database by their ID.
|
||||
/// #[tool]
|
||||
/// async fn get_user(&self, user_id: String) -> Result<User, Error> { ... }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// これにより以下が生成されます:
|
||||
/// - `GetUserArgs` 構造体(引数用)
|
||||
/// - `Tool_get_user` 構造体(Toolラッパー)
|
||||
/// This generates:
|
||||
/// - `GetUserArgs` struct (for arguments)
|
||||
/// - `Tool_get_user` struct (Tool wrapper)
|
||||
/// - `impl Tool for Tool_get_user`
|
||||
/// - `impl MyApp { fn get_user_tool(&self) -> Tool_get_user }`
|
||||
#[proc_macro_attribute]
|
||||
@@ -36,14 +36,14 @@ pub fn tool_registry(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
for item in &mut impl_block.items {
|
||||
if let ImplItem::Fn(method) = item {
|
||||
// #[tool] 属性を探す
|
||||
// Look for #[tool] attribute
|
||||
let mut is_tool = false;
|
||||
|
||||
// 属性を走査してtoolがあるか確認し、削除する
|
||||
// Iterate through attributes to check for tool and remove it
|
||||
method.attrs.retain(|attr| {
|
||||
if attr.path().is_ident("tool") {
|
||||
is_tool = true;
|
||||
false // 属性を削除
|
||||
false // Remove the attribute
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@@ -65,7 +65,7 @@ pub fn tool_registry(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
/// ドキュメントコメントから説明文を抽出
|
||||
/// Extract description from doc comments
|
||||
fn extract_doc_comment(attrs: &[Attribute]) -> String {
|
||||
let mut lines = Vec::new();
|
||||
|
||||
@@ -75,7 +75,7 @@ fn extract_doc_comment(attrs: &[Attribute]) -> String {
|
||||
if let syn::Expr::Lit(expr_lit) = &meta.value {
|
||||
if let Lit::Str(lit_str) = &expr_lit.lit {
|
||||
let line = lit_str.value();
|
||||
// 先頭の空白を1つだけ除去(/// の後のスペース)
|
||||
// Remove only the leading space (after ///)
|
||||
let trimmed = line.strip_prefix(' ').unwrap_or(&line);
|
||||
lines.push(trimmed.to_string());
|
||||
}
|
||||
@@ -87,7 +87,7 @@ fn extract_doc_comment(attrs: &[Attribute]) -> String {
|
||||
lines.join("\n")
|
||||
}
|
||||
|
||||
/// #[description = "..."] 属性から説明を抽出
|
||||
/// Extract description from #[description = "..."] attribute
|
||||
fn extract_description_attr(attrs: &[syn::Attribute]) -> Option<String> {
|
||||
for attr in attrs {
|
||||
if attr.path().is_ident("description") {
|
||||
@@ -103,19 +103,19 @@ fn extract_description_attr(attrs: &[syn::Attribute]) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// メソッドからTool実装を生成
|
||||
/// Generate Tool implementation from a method
|
||||
fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::TokenStream {
|
||||
let sig = &method.sig;
|
||||
let method_name = &sig.ident;
|
||||
let tool_name = method_name.to_string();
|
||||
|
||||
// 構造体名を生成(PascalCase変換)
|
||||
// Generate struct names (convert to PascalCase)
|
||||
let pascal_name = to_pascal_case(&method_name.to_string());
|
||||
let tool_struct_name = format_ident!("Tool{}", pascal_name);
|
||||
let args_struct_name = format_ident!("{}Args", pascal_name);
|
||||
let definition_name = format_ident!("{}_definition", method_name);
|
||||
|
||||
// ドキュメントコメントから説明を取得
|
||||
// Get description from doc comments
|
||||
let description = extract_doc_comment(&method.attrs);
|
||||
let description = if description.is_empty() {
|
||||
format!("Tool: {}", tool_name)
|
||||
@@ -123,7 +123,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
description
|
||||
};
|
||||
|
||||
// 引数を解析(selfを除く)
|
||||
// Parse arguments (excluding self)
|
||||
let args: Vec<_> = sig
|
||||
.inputs
|
||||
.iter()
|
||||
@@ -131,12 +131,12 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
if let FnArg::Typed(pat_type) = arg {
|
||||
Some(pat_type)
|
||||
} else {
|
||||
None // selfを除外
|
||||
None // Exclude self
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// 引数構造体のフィールドを生成
|
||||
// Generate argument struct fields
|
||||
let arg_fields: Vec<_> = args
|
||||
.iter()
|
||||
.map(|pat_type| {
|
||||
@@ -144,14 +144,14 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
let ty = &pat_type.ty;
|
||||
let desc = extract_description_attr(&pat_type.attrs);
|
||||
|
||||
// パターンから識別子を抽出
|
||||
// Extract identifier from pattern
|
||||
let field_name = if let Pat::Ident(pat_ident) = pat.as_ref() {
|
||||
&pat_ident.ident
|
||||
} else {
|
||||
panic!("Only simple identifiers are supported for tool arguments");
|
||||
};
|
||||
|
||||
// #[description] があればschemarsのdocに変換
|
||||
// Convert #[description] to schemars doc if present
|
||||
if let Some(desc_str) = desc {
|
||||
quote! {
|
||||
#[schemars(description = #desc_str)]
|
||||
@@ -165,7 +165,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
})
|
||||
.collect();
|
||||
|
||||
// execute内で引数を展開するコード
|
||||
// Code to expand arguments in execute
|
||||
let arg_names: Vec<_> = args
|
||||
.iter()
|
||||
.map(|pat_type| {
|
||||
@@ -178,17 +178,17 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
})
|
||||
.collect();
|
||||
|
||||
// メソッドが非同期かどうか
|
||||
// Check if method is async
|
||||
let is_async = sig.asyncness.is_some();
|
||||
|
||||
// 戻り値の型を解析してResult判定
|
||||
// Parse return type and determine if Result
|
||||
let awaiter = if is_async {
|
||||
quote! { .await }
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
// 戻り値がResultかどうかを判定
|
||||
// Determine if return type is Result
|
||||
let result_handling = if is_result_type(&sig.output) {
|
||||
quote! {
|
||||
match result {
|
||||
@@ -202,7 +202,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
}
|
||||
};
|
||||
|
||||
// 引数がない場合は空のArgs構造体を作成
|
||||
// Create empty Args struct if no arguments
|
||||
let args_struct_def = if arg_fields.is_empty() {
|
||||
quote! {
|
||||
#[derive(serde::Deserialize, schemars::JsonSchema)]
|
||||
@@ -217,10 +217,10 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
}
|
||||
};
|
||||
|
||||
// 引数がない場合のexecute処理
|
||||
// Execute body handling for no arguments case
|
||||
let execute_body = if args.is_empty() {
|
||||
quote! {
|
||||
// 引数なしでも空のJSONオブジェクトを許容
|
||||
// Allow empty JSON object even with no arguments
|
||||
let _: #args_struct_name = serde_json::from_str(input_json)
|
||||
.unwrap_or(#args_struct_name {});
|
||||
|
||||
@@ -253,7 +253,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
}
|
||||
|
||||
impl #self_ty {
|
||||
/// ToolDefinition を取得(Worker への登録用)
|
||||
/// Get ToolDefinition (for registering with Worker)
|
||||
pub fn #definition_name(&self) -> ::llm_worker::tool::ToolDefinition {
|
||||
let ctx = self.clone();
|
||||
::std::sync::Arc::new(move || {
|
||||
@@ -270,12 +270,12 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
||||
}
|
||||
}
|
||||
|
||||
/// 戻り値の型がResultかどうかを判定
|
||||
/// Determine if return type is Result
|
||||
fn is_result_type(return_type: &ReturnType) -> bool {
|
||||
match return_type {
|
||||
ReturnType::Default => false,
|
||||
ReturnType::Type(_, ty) => {
|
||||
// Type::Pathの場合、最後のセグメントが"Result"かチェック
|
||||
// For Type::Path, check if last segment is "Result"
|
||||
if let Type::Path(type_path) = ty.as_ref() {
|
||||
if let Some(segment) = type_path.path.segments.last() {
|
||||
return segment.ident == "Result";
|
||||
@@ -286,7 +286,7 @@ fn is_result_type(return_type: &ReturnType) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// snake_case を PascalCase に変換
|
||||
/// Convert snake_case to PascalCase
|
||||
fn to_pascal_case(s: &str) -> String {
|
||||
s.split('_')
|
||||
.map(|part| {
|
||||
@@ -299,20 +299,20 @@ fn to_pascal_case(s: &str) -> String {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// マーカー属性。`tool_registry` によって処理されるため、ここでは何もしない。
|
||||
/// Marker attribute. Does nothing here as it's processed by `tool_registry`.
|
||||
#[proc_macro_attribute]
|
||||
pub fn tool(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
item
|
||||
}
|
||||
|
||||
/// 引数属性用のマーカー。パース時に`tool_registry`で解釈される。
|
||||
/// Marker for argument attributes. Interpreted by `tool_registry` during parsing.
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore
|
||||
/// #[tool]
|
||||
/// async fn get_user(
|
||||
/// &self,
|
||||
/// #[description = "取得したいユーザーのID"] user_id: String
|
||||
/// #[description = "The ID of the user to retrieve"] user_id: String
|
||||
/// ) -> Result<User, Error> { ... }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
|
||||
Reference in New Issue
Block a user