workerのAPI設計

This commit is contained in:
Keisuke Hirata 2026-04-11 17:30:32 +09:00
parent fc8ff9362e
commit f241dafac8
3 changed files with 60 additions and 49 deletions

View File

@ -3,7 +3,7 @@
- [x] ツール出力の遅延読み込み設計 (ToolOutput / BlobStore / auto_summarize) - [x] ツール出力の遅延読み込み設計 (ToolOutput / BlobStore / auto_summarize)
- [ ] ツール設計 - [ ] ツール設計
- [ ] ツールの動的追加/削除 → [tickets/tool-dynamic-registry.md](tickets/tool-dynamic-registry.md) - [ ] ツールの動的追加/削除 → [tickets/tool-dynamic-registry.md](tickets/tool-dynamic-registry.md)
- [ ] ToolDefinition ファクトリの遅延初期化修正 → [tickets/worker-builder-api.md](tickets/worker-builder-api.md) - [ ] run() 自動ロックとファクトリ遅延初期化 → [tickets/worker-auto-lock.md](tickets/worker-auto-lock.md)
- [x] inspect ツール実装 - [x] inspect ツール実装
- [x] max_turns: マニフェストによるターン数制限 - [x] max_turns: マニフェストによるターン数制限
- [x] pod バイナリエントリポイント - [x] pod バイナリエントリポイント
@ -12,3 +12,5 @@
- [x] JSONL ストリーム変換ユーティリティ (protocol::stream) - [x] JSONL ストリーム変換ユーティリティ (protocol::stream)
- [x] Hook モジュールの llm-worker からの除去 → [tickets/remove-hook-module.md](tickets/remove-hook-module.md) - [x] Hook モジュールの llm-worker からの除去 → [tickets/remove-hook-module.md](tickets/remove-hook-module.md)
- [ ] api_key_file: ファイルパスによるAPIキー解決 → [tickets/api-key-file.md](tickets/api-key-file.md) - [ ] api_key_file: ファイルパスによるAPIキー解決 → [tickets/api-key-file.md](tickets/api-key-file.md)
- [ ] コンテキスト圧縮 (Prune + Compact) → [tickets/context-compaction.md](tickets/context-compaction.md)
- [ ] パーミッション: パターンベースのツール実行制御 → [tickets/permission-extension-point.md](tickets/permission-extension-point.md)

View File

@ -0,0 +1,57 @@
# Worker: run() 時の自動キャッシュロックと ToolDefinition ファクトリ遅延初期化
## 背景
現状の `Worker` は Type-state パターンで `Mutable` / `CacheLocked` の2状態を持つが、
`lock()` を呼ばなくても `run()` できてしまうため、キャッシュ保護の存在を知らないユーザーは
常に非最適パスを通ることになる。
また `register_tool()` 時に `ToolDefinition` のファクトリクロージャが即時呼び出しされており、
本来の意図である遅延初期化になっていない。
## 方針
### run() 時の自動ロック
`run()` の冒頭で、`Mutable` 状態なら自動的に `CacheLocked` へ遷移する。
これにより lock を知らないユーザーでも嫌でもキャッシュ保護される。
ターンの合間に history や system prompt を編集したい場合は、明示的に `unlock()` を挟む。
次の `run()` で再び自動ロックされる。
```rust
let mut worker = Worker::new(client);
worker.set_system_prompt("...");
worker.register_tool(my_tool)?;
// Mutable のまま run() → 自動で lock される
worker.run("Hello").await?;
// ターン間で内容を弄りたい場合
worker.unlock();
worker.history_mut().truncate(5);
// 次の run() で再 lock
worker.run("Continue").await?;
```
#### 設計ポイント
- `run()``&mut self` を取る以上、内部で状態遷移しても外部の型は変わらない。
実装は内部フラグ(`is_locked: bool`)で管理し、`Mutable` / `CacheLocked`
type-state はそのまま維持する。`Worker<C, Mutable>` の `run()` が内部で lock 相当の
処理を行い、`unlock()` が呼ばれるまでキャッシュ破壊的な操作を(ランタイムで)ブロックする
- `Worker<C, CacheLocked>` は従来どおり。明示的に `lock()` してから使うパスも残る
- interceptor, max_turns, callbacks 等キャッシュに影響しない設定は lock 状態でも自由に変更可能
### ToolDefinition ファクトリの遅延初期化
`register_tool()` は定義を蓄積するだけにし、ファクトリの実行を初回 `run()` まで遅延させる。
- `register_tool()``ToolDefinition` を Vec に push するだけ
- 初回 `run()` の自動 lock 時にファクトリを一括実行し、ToolServer を構築
- `unlock()` 後に追加登録された tool は次の `run()` で初期化
## 移行
- `lock()` / `unlock()` は引き続き使える(明示的なキャッシュ管理用)
- `Worker::new()``run()` のパスが自動保護されるため、既存コードは変更不要

View File

@ -1,48 +0,0 @@
# Worker API: Builder パターンによるキャッシュ保護の自動化
## 背景
現状の `Worker` は Type-state パターンで `Mutable` / `CacheLocked` の2状態を持つが、
`lock()` を呼ばなくても `run()` できてしまうため、知らないユーザーは最適でないパスを通る。
"Pit of success" になっていない。
## 方針
Builder パターンで「設定フェーズ」と「実行フェーズ」を自然に分離する。
```rust
// 設定フェーズ(自由に編集可能)
let worker = Worker::builder(client)
.system_prompt("You are a helpful assistant.")
.tool(my_tool)?
.hook(my_hook)
.build(); // ← ここで自動的にcache-protected状態へ
// 実行フェーズprefix不変、キャッシュ保護済み
worker.run("Hello").await?;
// 再設定が必要な場合
let builder = worker.reconfigure();
builder.tool(another_tool)?;
let worker = builder.build();
```
## 設計ポイント
- `build()` 後は常にキャッシュ保護状態。lock の存在をユーザーが意識する必要がない
- 設定と実行の分離が型で強制される(コンパイル時保証)
- `reconfigure()` でビルダーに戻せるため、動的なツール追加等にも対応可能
- Type-state の恩恵は維持しつつ、APIの認知負荷を下げる
## ToolDefinition ファクトリの遅延初期化
現状 `register_tool()` 時に `ToolDefinition` のファクトリクロージャが即時呼び出しされている。
Builder パターンへの移行に伴い、`build()` 時(= セッション開始時)まで遅延させる。
- `builder.tool(definition)` は定義を蓄積するだけ
- `build()` でファクトリを一括実行し、ToolServer を構築
## 移行
- 現行の `lock()` / `unlock()` は deprecated → 次メジャーで削除
- `Worker::new()``Worker::builder()` へ移行