feat: Redesign the tool system

This commit is contained in:
2026-01-10 00:31:14 +09:00
parent 5691b09fc8
commit 16fda38039
13 changed files with 897 additions and 396 deletions
+6 -6
View File
@@ -2,11 +2,11 @@
//!
//! ストリーミング受信中に別スレッドからキャンセルする例
use llm_worker::llm_client::providers::anthropic::AnthropicClient;
use llm_worker::{Worker, WorkerResult};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::Mutex;
use llm_worker::{Worker, WorkerResult};
use llm_worker::llm_client::providers::anthropic::AnthropicClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -21,8 +21,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
)
.init();
let api_key = std::env::var("ANTHROPIC_API_KEY")
.expect("ANTHROPIC_API_KEY environment variable not set");
let api_key =
std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY environment variable not set");
let client = AnthropicClient::new(&api_key, "claude-sonnet-4-20250514");
let worker = Arc::new(Mutex::new(Worker::new(client)));
@@ -41,7 +41,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let task = tokio::spawn(async move {
let mut w = worker_clone.lock().await;
println!("📡 Sending request to LLM...");
match w.run("Tell me a very long story about a brave knight. Make it as detailed as possible with many paragraphs.").await {
Ok(WorkerResult::Finished(_)) => {
println!("✅ Task completed normally");
@@ -66,6 +66,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
task.await?;
println!("\n✨ Demo complete!");
Ok(())
}
+14 -15
View File
@@ -41,7 +41,7 @@ use tracing_subscriber::EnvFilter;
use clap::{Parser, ValueEnum};
use llm_worker::{
Worker,
hook::{AfterToolCall, AfterToolCallResult, Hook, HookError, ToolResult},
hook::{Hook, HookError, PostToolCall, PostToolCallContext, PostToolCallResult},
llm_client::{
LlmClient,
providers::{
@@ -282,25 +282,22 @@ impl ToolResultPrinterHook {
}
#[async_trait]
impl Hook<AfterToolCall> for ToolResultPrinterHook {
async fn call(
&self,
tool_result: &mut ToolResult,
) -> Result<AfterToolCallResult, HookError> {
impl Hook<PostToolCall> for ToolResultPrinterHook {
async fn call(&self, ctx: &mut PostToolCallContext) -> Result<PostToolCallResult, HookError> {
let name = self
.call_names
.lock()
.unwrap()
.remove(&tool_result.tool_use_id)
.unwrap_or_else(|| tool_result.tool_use_id.clone());
.remove(&ctx.result.tool_use_id)
.unwrap_or_else(|| ctx.result.tool_use_id.clone());
if tool_result.is_error {
println!(" Result ({}): ❌ {}", name, tool_result.content);
if ctx.result.is_error {
println!(" Result ({}): ❌ {}", name, ctx.result.content);
} else {
println!(" Result ({}): ✅ {}", name, tool_result.content);
println!(" Result ({}): ✅ {}", name, ctx.result.content);
}
Ok(AfterToolCallResult::Continue)
Ok(PostToolCallResult::Continue)
}
}
@@ -441,8 +438,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// ツール登録(--no-tools でなければ)
if !args.no_tools {
let app = AppContext;
worker.register_tool(app.get_current_time_tool());
worker.register_tool(app.calculate_tool());
worker
.register_tool(app.get_current_time_definition())
.unwrap();
worker.register_tool(app.calculate_definition()).unwrap();
}
// ストリーミング表示用ハンドラーを登録
@@ -451,7 +450,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.on_text_block(StreamingPrinter::new())
.on_tool_use_block(ToolCallPrinter::new(tool_call_names.clone()));
worker.add_after_tool_call_hook(ToolResultPrinterHook::new(tool_call_names));
worker.add_post_tool_call_hook(ToolResultPrinterHook::new(tool_call_names));
// ワンショットモード
if let Some(prompt) = args.prompt {