feat: Implement HookEventKind
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
//! Worker のキャンセル機能のデモンストレーション
|
||||
//!
|
||||
//! ストリーミング受信中に別スレッドからキャンセルする例
|
||||
|
||||
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>> {
|
||||
// .envファイルを読み込む
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
// ロギング初期化
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
|
||||
)
|
||||
.init();
|
||||
|
||||
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)));
|
||||
|
||||
println!("🚀 Starting Worker...");
|
||||
println!("💡 Will cancel after 2 seconds\n");
|
||||
|
||||
// キャンセルトークンを先に取得(ロックを保持しない)
|
||||
let cancel_token = {
|
||||
let w = worker.lock().await;
|
||||
w.cancellation_token().clone()
|
||||
};
|
||||
|
||||
// タスク1: Workerを実行
|
||||
let worker_clone = worker.clone();
|
||||
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");
|
||||
}
|
||||
Ok(WorkerResult::Paused(_)) => {
|
||||
println!("⏸️ Task paused");
|
||||
}
|
||||
Err(e) => {
|
||||
println!("❌ Task error: {}", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// タスク2: 2秒後にキャンセル
|
||||
tokio::spawn(async move {
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
println!("\n🛑 Cancelling worker...");
|
||||
cancel_token.cancel();
|
||||
});
|
||||
|
||||
// タスク完了を待つ
|
||||
task.await?;
|
||||
|
||||
println!("\n✨ Demo complete!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -41,7 +41,7 @@ use tracing_subscriber::EnvFilter;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use llm_worker::{
|
||||
Worker,
|
||||
hook::{ControlFlow, HookError, ToolResult, WorkerHook},
|
||||
hook::{AfterToolCall, AfterToolCallResult, Hook, HookError, ToolResult},
|
||||
llm_client::{
|
||||
LlmClient,
|
||||
providers::{
|
||||
@@ -282,11 +282,11 @@ impl ToolResultPrinterHook {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl WorkerHook for ToolResultPrinterHook {
|
||||
async fn after_tool_call(
|
||||
impl Hook<AfterToolCall> for ToolResultPrinterHook {
|
||||
async fn call(
|
||||
&self,
|
||||
tool_result: &mut ToolResult,
|
||||
) -> Result<ControlFlow, HookError> {
|
||||
) -> Result<AfterToolCallResult, HookError> {
|
||||
let name = self
|
||||
.call_names
|
||||
.lock()
|
||||
@@ -300,7 +300,7 @@ impl WorkerHook for ToolResultPrinterHook {
|
||||
println!(" Result ({}): ✅ {}", name, tool_result.content);
|
||||
}
|
||||
|
||||
Ok(ControlFlow::Continue)
|
||||
Ok(AfterToolCallResult::Continue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,7 +451,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_hook(ToolResultPrinterHook::new(tool_call_names));
|
||||
worker.add_after_tool_call_hook(ToolResultPrinterHook::new(tool_call_names));
|
||||
|
||||
// ワンショットモード
|
||||
if let Some(prompt) = args.prompt {
|
||||
|
||||
Reference in New Issue
Block a user