docs: Tidying up comments

This commit is contained in:
2026-01-08 18:23:16 +09:00
parent 2487d1ece7
commit 9233bb9163
13 changed files with 554 additions and 114 deletions
+35 -6
View File
@@ -1,10 +1,39 @@
//! worker - LLMワーカーのメイン実装
//! worker - LLMワーカーライブラリ
//!
//! このクレートは以下を提供します:
//! - Worker: ターン制御を行う高レベルコンポーネント
//! - Timeline: イベントストリームの状態管理とハンドラーへのディスパッチ
//! - LlmClient: LLMプロバイダとの通信
//! - 型消去されたHandler実装
//! LLMとの対話を管理するコンポーネントを提供します
//!
//! # 主要なコンポーネント
//!
//! - [`Worker`] - LLMとの対話を管理する中心コンポーネント
//! - [`Tool`] - LLMから呼び出し可能なツール
//! - [`WorkerHook`] - ターン進行への介入
//! - [`WorkerSubscriber`] - ストリーミングイベントの購読
//!
//! # Quick Start
//!
//! ```ignore
//! use worker::{Worker, Message};
//!
//! // Workerを作成
//! let mut worker = Worker::new(client)
//! .system_prompt("You are a helpful assistant.");
//!
//! // ツールを登録(オプション)
//! worker.register_tool(my_tool);
//!
//! // 対話を実行
//! let history = worker.run("Hello!").await?;
//! ```
//!
//! # キャッシュ保護
//!
//! KVキャッシュのヒット率を最大化するには、[`Worker::lock()`]で
//! ロック状態に遷移してから実行してください。
//!
//! ```ignore
//! let mut locked = worker.lock();
//! locked.run("user input").await?;
//! ```
pub mod llm_client;
mod subscriber_adapter;
+11 -4
View File
@@ -1,12 +1,19 @@
//! LLMクライアント層
//!
//! LLMプロバイダと通信し、統一された`Event`ストリームを出力す
//! LLMプロバイダと通信し、統一された[`Event`](crate::Event)ストリームを出力します。
//!
//! # サポートするプロバイダ
//!
//! - Anthropic (Claude)
//! - OpenAI (GPT-4, etc.)
//! - Google (Gemini)
//! - Ollama (ローカルLLM)
//!
//! # アーキテクチャ
//!
//! - **client**: `LlmClient` trait定義
//! - **scheme**: APIスキーマ(リクエスト/レスポンス変換)
//! - **providers**: プロバイダ固有のHTTPクライアント実装
//! - [`LlmClient`] - プロバイダ共通のtrait
//! - `providers`: プロバイダ固有のクライアント実装
//! - `scheme`: APIスキーマ(リクエスト/レスポンス変換)
pub mod client;
pub mod error;
+35 -11
View File
@@ -1,6 +1,7 @@
//! Timeline層の実装
//! Timeline層
//!
//! イベントストリームを受信し、登録されたHandlerディスパッチする
//! LLMからのイベントストリームを受信し、登録されたHandlerディスパッチします。
//! 通常はWorker経由で使用しますが、直接使用することも可能です。
use std::marker::PhantomData;
@@ -10,9 +11,11 @@ use worker_types::*;
// Type-erased Handler
// =============================================================================
/// 型消去されたHandler trait
/// 型消去された`Handler` trait
///
/// 各Handlerは独自のScope型を持つため、Timelineで保持するには型消去が必要
/// 各Handlerは独自のScope型を持つため、Timelineで保持するには型消去が必要です。
/// 通常は直接使用せず、`Timeline::on_text_block()`などのメソッド経由で
/// 自動的にラップされます。
pub trait ErasedHandler<K: Kind>: Send {
/// イベントをディスパッチ
fn dispatch(&mut self, event: &K::Event);
@@ -22,7 +25,7 @@ pub trait ErasedHandler<K: Kind>: Send {
fn end_scope(&mut self);
}
/// Handler<K>からErasedHandler<K>のラッパー
/// `Handler<K>`を`ErasedHandler<K>`として扱うためのラッパー
pub struct HandlerWrapper<H, K>
where
H: Handler<K>,
@@ -316,13 +319,34 @@ where
// Timeline
// =============================================================================
/// Timeline - イベントストリームの状態管理とディスパッチ
/// イベントストリームの管理とハンドラへのディスパッチ
///
/// # 責務
/// 1. Eventストリームを受信
/// 2. Block系イベントをBlockKindごとのライフサイクルイベントに変換
/// 3. 各Handlerごとのスコープの生成・管理
/// 4. 登録されたHandlerへの登録順ディスパッチ
/// LLMからのイベントを受信し、登録されたハンドラに振り分けます。
/// ブロック系イベントはスコープ管理付きで処理されます。
///
/// # Examples
///
/// ```ignore
/// use worker::{Timeline, Handler, TextBlockKind, TextBlockEvent};
///
/// struct MyHandler;
/// impl Handler<TextBlockKind> for MyHandler {
/// type Scope = String;
/// fn on_event(&mut self, buffer: &mut String, event: &TextBlockEvent) {
/// if let TextBlockEvent::Delta(text) = event {
/// buffer.push_str(text);
/// }
/// }
/// }
///
/// let mut timeline = Timeline::new();
/// timeline.on_text_block(MyHandler);
/// ```
///
/// # サポートするイベント種別
///
/// - **メタ系**: Usage, Ping, Status, Error
/// - **ブロック系**: TextBlock, ThinkingBlock, ToolUseBlock
pub struct Timeline {
// Meta系ハンドラー
usage_handlers: Vec<Box<dyn ErasedHandler<UsageKind>>>,
+96 -19
View File
@@ -82,20 +82,40 @@ impl<S: WorkerSubscriber + 'static> TurnNotifier for SubscriberTurnNotifier<S> {
// Worker
// =============================================================================
/// Worker - ターン制御コンポーネント
/// LLMとの対話を管理する中心コンポーネント
///
/// Type-stateパターンによりキャッシュ保護を実現する。
/// ユーザーからの入力を受け取り、LLMにリクエストを送信し、
/// ツール呼び出しがあれば自動的に実行してターンを進行させます。
///
/// # 状態
/// - `Mutable`: 初期状態。システムプロンプトや履歴を自由に編集可能。
/// - `Locked`: キャッシュ保護状態。前方コンテキストは不変となり、追記のみ可能。
/// # 状態遷移(Type-state
///
/// # 責務
/// - LLMへのリクエスト送信とレスポンス処理
/// - ツール呼び出しの収集と実行
/// - Hookによる介入の提供
/// - ターンループの制御
/// - 履歴の所有と管理
/// - [`Mutable`]: 初期状態。システムプロンプトや履歴を自由に編集可能。
/// - [`Locked`]: キャッシュ保護状態。`lock()`で遷移。前方コンテキストは不変。
///
/// # Examples
///
/// ```ignore
/// use worker::{Worker, Message};
///
/// // Workerを作成してツールを登録
/// let mut worker = Worker::new(client)
/// .system_prompt("You are a helpful assistant.");
/// worker.register_tool(my_tool);
///
/// // 対話を実行
/// let history = worker.run("Hello!").await?;
/// ```
///
/// # キャッシュ保護が必要な場合
///
/// ```ignore
/// let mut worker = Worker::new(client)
/// .system_prompt("...");
///
/// // 履歴を設定後、ロックしてキャッシュを保護
/// let mut locked = worker.lock();
/// locked.run("user input").await?;
/// ```
pub struct Worker<C: LlmClient, S: WorkerState = Mutable> {
/// LLMクライアント
client: C,
@@ -128,13 +148,37 @@ pub struct Worker<C: LlmClient, S: WorkerState = Mutable> {
// =============================================================================
impl<C: LlmClient, S: WorkerState> Worker<C, S> {
/// WorkerSubscriberを登録
/// イベント購読者を登録する
///
/// Subscriberは以下のイベントを受け取ることができる:
/// - ブロックイベント: on_text_block, on_tool_use_block
/// - 単発イベント: on_usage, on_status, on_error
/// - 累積イベント: on_text_complete, on_tool_call_complete
/// - ターン制御: on_turn_start, on_turn_end
/// 登録したSubscriberは、LLMからのストリーミングイベントを
/// リアルタイムで受信できます。UIへのストリーム表示などに利用します。
///
/// # 受信できるイベント
///
/// - **ブロックイベント**: `on_text_block`, `on_tool_use_block`
/// - **メタイベント**: `on_usage`, `on_status`, `on_error`
/// - **完了イベント**: `on_text_complete`, `on_tool_call_complete`
/// - **ターン制御**: `on_turn_start`, `on_turn_end`
///
/// # Examples
///
/// ```ignore
/// use worker::{Worker, WorkerSubscriber, TextBlockEvent};
///
/// struct MyPrinter;
/// impl WorkerSubscriber for MyPrinter {
/// type TextBlockScope = ();
/// type ToolUseBlockScope = ();
///
/// fn on_text_block(&mut self, _: &mut (), event: &TextBlockEvent) {
/// if let TextBlockEvent::Delta(text) = event {
/// print!("{}", text);
/// }
/// }
/// }
///
/// worker.subscribe(MyPrinter);
/// ```
pub fn subscribe<Sub: WorkerSubscriber + 'static>(&mut self, subscriber: Sub) {
let subscriber = Arc::new(Mutex::new(subscriber));
@@ -159,7 +203,19 @@ impl<C: LlmClient, S: WorkerState> Worker<C, S> {
.push(Box::new(SubscriberTurnNotifier { subscriber }));
}
/// ツールを登録
/// ツールを登録する
///
/// 登録されたツールはLLMからの呼び出しで自動的に実行されます。
/// 同名のツールを登録した場合、後から登録したものが優先されます。
///
/// # Examples
///
/// ```ignore
/// use worker::Worker;
/// use my_tools::SearchTool;
///
/// worker.register_tool(SearchTool::new());
/// ```
pub fn register_tool(&mut self, tool: impl Tool + 'static) {
let name = tool.name().to_string();
self.tools.insert(name, Arc::new(tool));
@@ -172,7 +228,28 @@ impl<C: LlmClient, S: WorkerState> Worker<C, S> {
}
}
/// Hookを追加
/// Hookを追加する
///
/// Hookはターンの進行・ツール実行に介入できます。
/// 複数のHookを登録した場合、登録順に実行されます。
///
/// # Examples
///
/// ```ignore
/// use worker::{Worker, WorkerHook, ControlFlow, ToolCall};
///
/// struct LoggingHook;
///
/// #[async_trait::async_trait]
/// impl WorkerHook for LoggingHook {
/// async fn before_tool_call(&self, call: &mut ToolCall) -> Result<ControlFlow, HookError> {
/// println!("Calling tool: {}", call.name);
/// Ok(ControlFlow::Continue)
/// }
/// }
///
/// worker.add_hook(LoggingHook);
/// ```
pub fn add_hook(&mut self, hook: impl WorkerHook + 'static) {
self.hooks.push(Box::new(hook));
}