From f241dafac8afe1bb2102d610fff50c1ffeab1a4f Mon Sep 17 00:00:00 2001 From: Hare Date: Sat, 11 Apr 2026 17:30:32 +0900 Subject: [PATCH] =?UTF-8?q?worker=E3=81=AEAPI=E8=A8=AD=E8=A8=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 4 ++- tickets/worker-auto-lock.md | 57 +++++++++++++++++++++++++++++++++++ tickets/worker-builder-api.md | 48 ----------------------------- 3 files changed, 60 insertions(+), 49 deletions(-) create mode 100644 tickets/worker-auto-lock.md delete mode 100644 tickets/worker-builder-api.md diff --git a/TODO.md b/TODO.md index 22147d6f..d7ad572f 100644 --- a/TODO.md +++ b/TODO.md @@ -3,7 +3,7 @@ - [x] ツール出力の遅延読み込み設計 (ToolOutput / BlobStore / auto_summarize) - [ ] ツール設計 - [ ] ツールの動的追加/削除 → [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] max_turns: マニフェストによるターン数制限 - [x] pod バイナリエントリポイント @@ -12,3 +12,5 @@ - [x] JSONL ストリーム変換ユーティリティ (protocol::stream) - [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) +- [ ] コンテキスト圧縮 (Prune + Compact) → [tickets/context-compaction.md](tickets/context-compaction.md) +- [ ] パーミッション: パターンベースのツール実行制御 → [tickets/permission-extension-point.md](tickets/permission-extension-point.md) diff --git a/tickets/worker-auto-lock.md b/tickets/worker-auto-lock.md new file mode 100644 index 00000000..290ffbf6 --- /dev/null +++ b/tickets/worker-auto-lock.md @@ -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` の `run()` が内部で lock 相当の + 処理を行い、`unlock()` が呼ばれるまでキャッシュ破壊的な操作を(ランタイムで)ブロックする +- `Worker` は従来どおり。明示的に `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()` のパスが自動保護されるため、既存コードは変更不要 diff --git a/tickets/worker-builder-api.md b/tickets/worker-builder-api.md deleted file mode 100644 index 75c9e93a..00000000 --- a/tickets/worker-builder-api.md +++ /dev/null @@ -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()` へ移行