From 1d6125e57dd5f0d1097c29830544369730df0ed5 Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 25 Jun 2026 22:26:27 +0900 Subject: [PATCH 1/7] ticket: route llm engine rename task --- .../artifacts/orchestration-plan.jsonl | 1 + .yoi/tickets/00001KVZD10ED/item.md | 2 +- .yoi/tickets/00001KVZD10ED/thread.md | 77 +++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 .yoi/tickets/00001KVZD10ED/artifacts/orchestration-plan.jsonl diff --git a/.yoi/tickets/00001KVZD10ED/artifacts/orchestration-plan.jsonl b/.yoi/tickets/00001KVZD10ED/artifacts/orchestration-plan.jsonl new file mode 100644 index 00000000..d2fe0c57 --- /dev/null +++ b/.yoi/tickets/00001KVZD10ED/artifacts/orchestration-plan.jsonl @@ -0,0 +1 @@ +{"id":"orch-plan-20260625-132518-1","ticket_id":"00001KVZD10ED","kind":"accepted_plan","accepted_plan":{"summary":"Ticket `00001KVZD10ED` は implementation_ready。専用 worktree `/home/hare/Projects/yoi/.worktree/00001KVZD10ED-llm-engine-rename` と branch `work/00001KVZD10ED-llm-engine-rename` で、`llm-worker` / `llm-worker-macros` を `llm-engine` / `llm-engine-macros` に rename し、主要 public turn-engine 型を `Worker` から `Engine` 系へ rename する。責務移動や worker-runtime 実装、互換 alias は non-goal。","branch":"work/00001KVZD10ED-llm-engine-rename","worktree":"/home/hare/Projects/yoi/.worktree/00001KVZD10ED-llm-engine-rename","role_plan":"Orchestrator: accept/routing, worktree creation, final integration/validation/cleanup. Coder: repository-wide crate/type rename in dedicated child worktree. Reviewer: read-only review focusing on mechanical rename completeness, no compatibility alias, no behavior/authority movement, and validation evidence."},"author":"yoi-orchestrator","at":"2026-06-25T13:25:18Z"} diff --git a/.yoi/tickets/00001KVZD10ED/item.md b/.yoi/tickets/00001KVZD10ED/item.md index 5aef016b..9bc20ca6 100644 --- a/.yoi/tickets/00001KVZD10ED/item.md +++ b/.yoi/tickets/00001KVZD10ED/item.md @@ -2,7 +2,7 @@ title: 'llm-worker crateをllm-engineへ改名する' state: 'queued' created_at: '2026-06-25T12:45:38Z' -updated_at: '2026-06-25T13:24:26Z' +updated_at: '2026-06-25T13:26:00Z' assignee: null queued_by: 'workspace-panel' queued_at: '2026-06-25T13:24:26Z' diff --git a/.yoi/tickets/00001KVZD10ED/thread.md b/.yoi/tickets/00001KVZD10ED/thread.md index c790479e..5f5ca942 100644 --- a/.yoi/tickets/00001KVZD10ED/thread.md +++ b/.yoi/tickets/00001KVZD10ED/thread.md @@ -30,4 +30,81 @@ Marked ready by `yoi ticket state`. Ticket を `workspace-panel` が queued にしました。 +--- + + + +## Decision + +Routing decision: implementation_ready + +Reason: +- Dashboard Queue により人間が Orchestrator routing を許可した queued Ticket として確認した。 +- Ticket body は `llm-worker` / `llm-worker-macros` crate rename、Rust import path rename、major public type rename (`Worker` -> `Engine`, config/result/error names)、repo-wide references、validation を具体的に列挙している。 +- `TicketRelationQuery` は blocking relation 0 件、`TicketOrchestrationPlanQuery` は routing 前 plan 0 件だった。 +- bounded context check で repository-wide `llm-worker` / `llm_worker` references を確認し、主な変更 surface は `crates/llm-worker`, `crates/llm-worker-macros`, workspace/dependency metadata, `pod`/`manifest` imports, docs/tests/examples/Nix/Cargo.lock である。これは大きめだが mechanical rename task として明確で、責務移動や WorkerRuntime 実装は non-goal として分離されている。 +- risk は API/naming churn だが、受け入れ条件と validation が明確で、Coder の bounded implementation latitude に収まる。planning return が必要な未決定事項は見つからない。 + +Evidence checked: +- Ticket body / thread: `item.md`, `thread.md`。thread は create、planning->ready、ready->queued のみで未解決 blocker は記録されていない。 +- Relations / orchestration plan: relation 0 件、routing 前 plan 0 件。accepted plan `orch-plan-20260625-132518-1` を記録済み。 +- Code context: `git grep` で `crates/llm-worker`, `crates/llm-worker-macros`, `llm_worker`, `llm_worker_macros`, `Worker` imports/examples/tests/docs references を確認。 +- Workspace state: `/home/hare/Projects/yoi/.worktree/orchestration` は clean。queued Ticket はこの 1 件、inprogress Ticket は 0 件。 + +IntentPacket: + +Intent: +- LLM turn-processing crate を `llm-worker` から `llm-engine` へ rename し、public turn-engine主体型を `Worker` から `Engine` 系へ rename することで、今後の Runtime-scoped Worker concept と衝突しない package/API naming に整理する。 + +Binding decisions / invariants: +- `llm-engine` は LLM turn engine。Runtime / Worker identity / process lifecycle / socket protocol / session file authority は持たない。 +- 責務移動は最小限。provider request/stream handling、tool-call loop、reasoning/usage/retry/continuation/history/callback semantics は変えない。 +- `crates/llm-worker` / `crates/llm-worker-macros` は残さない。 +- `llm-worker` / `llm_worker` / `llm_worker_macros` compatibility alias は作らない。 +- `pod` crate and dependents should compile against `llm_engine::Engine` and renamed config/result/error types. +- New `worker-runtime` crate or Pod->Worker migration is non-goal. + +Requirements / acceptance criteria: +- `crates/llm-engine` and `crates/llm-engine-macros` exist; old directories gone. +- Cargo package/dependency names and Rust import paths use `llm-engine` / `llm_engine` and `llm-engine-macros` / `llm_engine_macros`. +- Public turn-engine type is `llm_engine::Engine`, not `Worker`; config/result/error names no longer use `Worker` for the turn engine concept. +- Repository-wide old references are gone except intentional historical/migration notes if any. +- `pod`, `manifest`, `yoi`, examples/tests/docs/Nix/Cargo.lock update consistently. +- Existing runtime behavior is unchanged except names. +- Validation target includes `cargo test -p llm-engine`, `cargo test -p pod`, `cargo check -p yoi`, `git diff --check`, `nix build .#yoi --no-link`. + +Implementation latitude: +- Result/output type exact names may follow Ticket guidance (`EngineRunResult`, `EngineRunOutput`, etc.) as long as public API no longer presents LLM turn engine as Worker. +- Internal file names may be renamed for clarity (`worker.rs` -> `engine.rs`) if practical; otherwise public module/API must be clean. +- Historical ticket ids or changelog-like references may remain only if clearly intentional and not active API/docs guidance. + +Escalate if: +- Rename requires behavior changes to provider streaming/tool-loop/history semantics. +- A compatibility alias appears necessary to make internal crates compile. +- Existing macro/test generated names cannot be renamed without broader procedural macro redesign. +- `cargo test -p pod` failure is not the known prompt guidance snapshot caveat but a rename regression. + +Validation: +- `cargo test -p llm-engine` +- `cargo test -p pod` +- `cargo check -p yoi` +- `git diff --check` +- `nix build .#yoi --no-link` +- Add focused grep evidence for old names. + +Current code map: +- Primary: `crates/llm-worker`, `crates/llm-worker-macros`, workspace `Cargo.toml`, `Cargo.lock`, `package.nix`。 +- Secondary: dependent imports in `crates/pod`, `crates/manifest`, examples/tests/docs/resources as found by grep。 +- Avoid: worker-runtime implementation, Pod runtime migration, session/socket authority changes, provider/tool-loop behavior changes。 + +Critical risks / reviewer focus: +- stale old crate/import/type references。 +- hidden compatibility alias left behind。 +- behavior changes mixed into mechanical rename。 +- `Worker` remaining as public turn-engine主体名 where it conflicts with Runtime Worker concept。 +- Nix/Cargo lock/hash updates missed。 + +Next action: +- `queued -> inprogress` を記録してから worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVZD10ED-llm-engine-rename` を作成し、multi-agent-workflow で Coder/Reviewer sibling loop に進める。 + --- From 22598710fd881d5d2fa4663e2d15f3821c1b81fa Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 25 Jun 2026 22:27:24 +0900 Subject: [PATCH 2/7] ticket: accept llm engine rename task --- .yoi/tickets/00001KVZD10ED/item.md | 4 ++-- .yoi/tickets/00001KVZD10ED/thread.md | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.yoi/tickets/00001KVZD10ED/item.md b/.yoi/tickets/00001KVZD10ED/item.md index 9bc20ca6..867bc3a8 100644 --- a/.yoi/tickets/00001KVZD10ED/item.md +++ b/.yoi/tickets/00001KVZD10ED/item.md @@ -1,8 +1,8 @@ --- title: 'llm-worker crateをllm-engineへ改名する' -state: 'queued' +state: 'inprogress' created_at: '2026-06-25T12:45:38Z' -updated_at: '2026-06-25T13:26:00Z' +updated_at: '2026-06-25T13:26:35Z' assignee: null queued_by: 'workspace-panel' queued_at: '2026-06-25T13:24:26Z' diff --git a/.yoi/tickets/00001KVZD10ED/thread.md b/.yoi/tickets/00001KVZD10ED/thread.md index 5f5ca942..0d22b609 100644 --- a/.yoi/tickets/00001KVZD10ED/thread.md +++ b/.yoi/tickets/00001KVZD10ED/thread.md @@ -108,3 +108,16 @@ Next action: - `queued -> inprogress` を記録してから worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVZD10ED-llm-engine-rename` を作成し、multi-agent-workflow で Coder/Reviewer sibling loop に進める。 --- + + + +## State changed + +Orchestrator acceptance: queued -> inprogress + +- 直前確認で `TicketShow` は state `queued`、blocking relation は 0 件、accepted plan `orch-plan-20260625-132518-1` を確認した。 +- routing decision と IntentPacket は Ticket thread に記録済み。 +- orchestration worktree は clean。この Ticket 用 worktree/branch はまだ作成していない。 +- これ以降に worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVZD10ED-llm-engine-rename` を作成し、multi-agent-workflow に接続する。 + +--- From 230b379979385f9145281b87fc8c2c5982d4e0fa Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 25 Jun 2026 22:28:33 +0900 Subject: [PATCH 3/7] ticket: record llm engine coder start --- .yoi/tickets/00001KVZD10ED/item.md | 2 +- .yoi/tickets/00001KVZD10ED/thread.md | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.yoi/tickets/00001KVZD10ED/item.md b/.yoi/tickets/00001KVZD10ED/item.md index 867bc3a8..0dea36cd 100644 --- a/.yoi/tickets/00001KVZD10ED/item.md +++ b/.yoi/tickets/00001KVZD10ED/item.md @@ -2,7 +2,7 @@ title: 'llm-worker crateをllm-engineへ改名する' state: 'inprogress' created_at: '2026-06-25T12:45:38Z' -updated_at: '2026-06-25T13:26:35Z' +updated_at: '2026-06-25T13:28:20Z' assignee: null queued_by: 'workspace-panel' queued_at: '2026-06-25T13:24:26Z' diff --git a/.yoi/tickets/00001KVZD10ED/thread.md b/.yoi/tickets/00001KVZD10ED/thread.md index 0d22b609..8b7c30c1 100644 --- a/.yoi/tickets/00001KVZD10ED/thread.md +++ b/.yoi/tickets/00001KVZD10ED/thread.md @@ -121,3 +121,16 @@ Orchestrator acceptance: queued -> inprogress - これ以降に worktree-workflow で `/home/hare/Projects/yoi/.worktree/00001KVZD10ED-llm-engine-rename` を作成し、multi-agent-workflow に接続する。 --- + + + +## Implementation report + +Implementation orchestration update: + +- worktree-workflow に従い、implementation worktree `/home/hare/Projects/yoi/.worktree/00001KVZD10ED-llm-engine-rename` と branch `work/00001KVZD10ED-llm-engine-rename` を作成した。 +- child worktree では tracked `.yoi` project records を見える状態にし、`.yoi/memory`、local/runtime/log/lock/secret-like `.yoi` paths を sparse-checkout で除外する方針にした。 +- Coder Pod `yoi-coder-00001KVZD10ED-llm-engine` を sibling として起動した。write scope は child worktree に限定し、runtime workspace root `/home/hare/Projects/yoi` は startup 要件を満たすため non-recursive read のみにした。 +- Coder には root/original workspace と orchestration worktree で read/write/validation/git operation を行わないよう明示した。 + +--- From 292fc4ea5d50d83cf457f561000e98369baa5c47 Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 25 Jun 2026 22:46:26 +0900 Subject: [PATCH 4/7] refactor: rename llm worker crate to engine --- Cargo.lock | 22 +- Cargo.toml | 12 +- crates/client/README.md | 2 +- .../Cargo.toml | 4 +- .../README.md | 4 +- .../src/lib.rs | 18 +- crates/{llm-worker => llm-engine}/Cargo.toml | 4 +- crates/{llm-worker => llm-engine}/README.md | 10 +- .../docs/architecture.md | 12 +- .../docs/requirements.md | 20 +- .../examples/engine_cancel_demo.rs} | 26 +- .../examples/engine_cli.rs} | 50 +-- .../examples/record_test_fixtures/main.rs | 6 +- .../examples/record_test_fixtures/recorder.rs | 4 +- .../record_test_fixtures/scenarios.rs | 2 +- .../src/callback.rs | 10 +- .../worker.rs => llm-engine/src/engine.rs} | 225 ++++++------- .../{llm-worker => llm-engine}/src/event.rs | 2 +- .../{llm-worker => llm-engine}/src/handler.rs | 2 +- .../src/interceptor.rs | 26 +- crates/{llm-worker => llm-engine}/src/lib.rs | 33 +- .../src/llm_client/auth.rs | 4 +- .../src/llm_client/capability.rs | 0 .../src/llm_client/client.rs | 2 +- .../src/llm_client/error.rs | 0 .../src/llm_client/event.rs | 0 .../src/llm_client/mod.rs | 0 .../src/llm_client/retry.rs | 6 +- .../llm_client/scheme/anthropic/capability.rs | 0 .../src/llm_client/scheme/anthropic/events.rs | 0 .../src/llm_client/scheme/anthropic/mod.rs | 0 .../llm_client/scheme/anthropic/request.rs | 0 .../scheme/anthropic/scheme_impl.rs | 0 .../llm_client/scheme/gemini/capability.rs | 0 .../src/llm_client/scheme/gemini/events.rs | 0 .../src/llm_client/scheme/gemini/mod.rs | 0 .../src/llm_client/scheme/gemini/request.rs | 0 .../llm_client/scheme/gemini/scheme_impl.rs | 0 .../src/llm_client/scheme/mod.rs | 0 .../scheme/openai_chat/capability.rs | 0 .../llm_client/scheme/openai_chat/events.rs | 0 .../src/llm_client/scheme/openai_chat/mod.rs | 0 .../llm_client/scheme/openai_chat/request.rs | 0 .../scheme/openai_chat/scheme_impl.rs | 0 .../scheme/openai_responses/capability.rs | 0 .../scheme/openai_responses/events.rs | 0 .../llm_client/scheme/openai_responses/mod.rs | 0 .../scheme/openai_responses/request.rs | 0 .../scheme/openai_responses/scheme_impl.rs | 0 .../src/llm_client/transport.rs | 0 .../src/llm_client/types.rs | 2 +- .../{llm-worker => llm-engine}/src/message.rs | 0 .../{llm-worker => llm-engine}/src/prune.rs | 10 +- .../{llm-worker => llm-engine}/src/state.rs | 26 +- .../src/timeline/event.rs | 0 .../src/timeline/mod.rs | 0 .../src/timeline/text_block_collector.rs | 0 .../src/timeline/thinking_block_collector.rs | 0 .../src/timeline/timeline.rs | 4 +- .../src/timeline/tool_call_collector.rs | 0 .../src/token_counter.rs | 0 crates/{llm-worker => llm-engine}/src/tool.rs | 24 +- .../src/tool_server.rs | 16 +- .../src/usage_record.rs | 0 .../tests/anthropic_fixtures.rs | 0 .../tests/callback_test.rs | 76 ++--- .../tests/common/mod.rs | 8 +- .../tests/compile_fail.rs | 0 .../tests/engine_fixtures.rs} | 56 ++-- .../tests/engine_state_test.rs} | 182 +++++------ .../anthropic/anthropic_1767624445.jsonl | 0 .../fixtures/anthropic/simple_text.jsonl | 0 .../tests/fixtures/anthropic/tool_call.jsonl | 0 .../tests/fixtures/gemini/long_text.jsonl | 0 .../tests/fixtures/gemini/simple_text.jsonl | 0 .../tests/fixtures/gemini/tool_call.jsonl | 0 .../tests/fixtures/ollama/long_text.jsonl | 0 .../tests/fixtures/ollama/simple_text.jsonl | 0 .../tests/fixtures/ollama/tool_call.jsonl | 0 .../tests/fixtures/openai/long_text.jsonl | 0 .../fixtures/openai/openai_1767708975.jsonl | 0 .../tests/fixtures/openai/simple_text.jsonl | 0 .../tests/fixtures/openai/tool_call.jsonl | 0 .../tests/gemini_fixtures.rs | 0 .../tests/ollama_fixtures.rs | 0 .../tests/openai_fixtures.rs | 0 .../tests/parallel_execution_test.rs | 90 +++--- .../tests/reasoning_round_trip_test.rs | 50 +-- .../tests/tool_macro_test.rs | 4 +- .../tests/transport_retry_test.rs | 18 +- .../tests/ui/locked_register_tool.rs | 14 +- .../tests/ui/locked_register_tool.stderr | 6 +- .../ui/tool_server_handle_register_tool.rs | 14 +- .../tool_server_handle_register_tool.stderr | 2 +- crates/manifest/Cargo.toml | 2 +- crates/manifest/src/model.rs | 4 +- crates/mcp/tests/stdio_lifecycle.rs | 2 +- crates/memory/Cargo.toml | 2 +- crates/memory/README.md | 2 +- crates/memory/src/consolidate/input.rs | 6 +- crates/memory/src/consolidate/lock.rs | 2 +- crates/memory/src/consolidate/mod.rs | 8 +- crates/memory/src/extract/input.rs | 12 +- crates/memory/src/extract/mod.rs | 4 +- crates/memory/src/extract/tool.rs | 16 +- crates/memory/src/tool/delete.rs | 4 +- crates/memory/src/tool/edit.rs | 4 +- crates/memory/src/tool/mod.rs | 4 +- crates/memory/src/tool/query.rs | 6 +- crates/memory/src/tool/read.rs | 4 +- crates/memory/src/tool/write.rs | 4 +- crates/plugin-pdk/tests/template.rs | 2 +- crates/pod-store/README.md | 2 +- crates/pod/Cargo.toml | 2 +- crates/pod/README.md | 6 +- crates/pod/examples/pod_cli.rs | 2 +- crates/pod/src/active_workflow.rs | 6 +- crates/pod/src/compact/metrics_tracker.rs | 2 +- crates/pod/src/compact/prune.rs | 20 +- crates/pod/src/compact/token_counter.rs | 16 +- crates/pod/src/compact/usage_tracker.rs | 6 +- crates/pod/src/compact/worker.rs | 24 +- crates/pod/src/controller.rs | 50 +-- crates/pod/src/discovery.rs | 8 +- crates/pod/src/feature.rs | 40 +-- crates/pod/src/feature/builtin/task/mod.rs | 2 +- crates/pod/src/feature/builtin/task/store.rs | 2 +- .../pod/src/feature/builtin/task/tool_impl.rs | 10 +- crates/pod/src/feature/builtin/ticket.rs | 2 +- crates/pod/src/feature/mcp.rs | 2 +- crates/pod/src/feature/plugin.rs | 2 +- crates/pod/src/fs_view.rs | 4 +- crates/pod/src/hook.rs | 14 +- crates/pod/src/interrupt_prep.rs | 2 +- crates/pod/src/ipc/alerter.rs | 6 +- crates/pod/src/ipc/interceptor.rs | 28 +- crates/pod/src/ipc/notify_buffer.rs | 2 +- crates/pod/src/permission.rs | 2 +- crates/pod/src/pod.rs | 298 +++++++++--------- crates/pod/src/prompt/catalog.rs | 8 +- crates/pod/src/prompt/system.rs | 2 +- crates/pod/src/segment_log_sink.rs | 2 +- crates/pod/src/shutdown_after_idle.rs | 2 +- crates/pod/src/spawn/comm_tools.rs | 10 +- crates/pod/src/spawn/tool.rs | 4 +- crates/pod/src/ticket_event_notify.rs | 2 +- crates/pod/src/workflow/mod.rs | 4 +- crates/pod/tests/compact_events_test.rs | 16 +- crates/pod/tests/consolidation_test.rs | 10 +- crates/pod/tests/controller_test.rs | 76 ++--- crates/pod/tests/pod_comm_tools_test.rs | 4 +- crates/pod/tests/session_metrics_test.rs | 16 +- crates/pod/tests/spawn_pod_test.rs | 2 +- .../pod/tests/system_prompt_template_test.rs | 32 +- crates/protocol/README.md | 2 +- crates/protocol/src/lib.rs | 10 +- crates/provider/Cargo.toml | 2 +- crates/provider/README.md | 6 +- crates/provider/src/catalog.rs | 2 +- crates/provider/src/codex_oauth/error.rs | 2 +- crates/provider/src/codex_oauth/mod.rs | 6 +- crates/provider/src/lib.rs | 4 +- crates/session-metrics/README.md | 2 +- crates/session-store/Cargo.toml | 2 +- crates/session-store/README.md | 2 +- crates/session-store/src/event_trace.rs | 2 +- crates/session-store/src/lib.rs | 8 +- crates/session-store/src/logged_item.rs | 4 +- crates/session-store/src/segment.rs | 20 +- crates/session-store/src/segment_log.rs | 26 +- crates/session-store/src/store.rs | 2 +- crates/session-store/src/system_item.rs | 2 +- crates/session-store/tests/common/mod.rs | 4 +- crates/session-store/tests/fs_store_test.rs | 10 +- crates/session-store/tests/session_test.rs | 40 +-- crates/ticket/Cargo.toml | 2 +- crates/ticket/src/tool.rs | 28 +- crates/tools/Cargo.toml | 2 +- crates/tools/README.md | 2 +- crates/tools/src/bash.rs | 10 +- crates/tools/src/edit.rs | 4 +- crates/tools/src/error.rs | 4 +- crates/tools/src/glob.rs | 4 +- crates/tools/src/grep.rs | 4 +- crates/tools/src/lib.rs | 8 +- crates/tools/src/read.rs | 4 +- crates/tools/src/tracker.rs | 4 +- crates/tools/src/web.rs | 6 +- crates/tools/src/write.rs | 8 +- crates/tools/tests/edge_cases.rs | 4 +- crates/tools/tests/integration.rs | 8 +- crates/tui/Cargo.toml | 2 +- crates/tui/src/app.rs | 12 +- crates/tui/src/pod_list.rs | 2 +- crates/yoi/README.md | 2 +- docs/design/context-history.md | 2 +- docs/design/overview.md | 8 +- docs/design/plugin-component-model.md | 6 +- docs/design/plugin-packages.md | 2 +- docs/design/provider-model-boundary.md | 8 +- docs/development/plugin-development.md | 2 +- package.nix | 2 +- 202 files changed, 1129 insertions(+), 1125 deletions(-) rename crates/{llm-worker-macros => llm-engine-macros}/Cargo.toml (74%) rename crates/{llm-worker-macros => llm-engine-macros}/README.md (88%) rename crates/{llm-worker-macros => llm-engine-macros}/src/lib.rs (94%) rename crates/{llm-worker => llm-engine}/Cargo.toml (93%) rename crates/{llm-worker => llm-engine}/README.md (78%) rename crates/{llm-worker => llm-engine}/docs/architecture.md (90%) rename crates/{llm-worker => llm-engine}/docs/requirements.md (72%) rename crates/{llm-worker/examples/worker_cancel_demo.rs => llm-engine/examples/engine_cancel_demo.rs} (69%) rename crates/{llm-worker/examples/worker_cli.rs => llm-engine/examples/engine_cli.rs} (93%) rename crates/{llm-worker => llm-engine}/examples/record_test_fixtures/main.rs (97%) rename crates/{llm-worker => llm-engine}/examples/record_test_fixtures/recorder.rs (96%) rename crates/{llm-worker => llm-engine}/examples/record_test_fixtures/scenarios.rs (97%) rename crates/{llm-worker => llm-engine}/src/callback.rs (97%) rename crates/{llm-worker/src/worker.rs => llm-engine/src/engine.rs} (93%) rename crates/{llm-worker => llm-engine}/src/event.rs (73%) rename crates/{llm-worker => llm-engine}/src/handler.rs (98%) rename crates/{llm-worker => llm-engine}/src/interceptor.rs (89%) rename crates/{llm-worker => llm-engine}/src/lib.rs (65%) rename crates/{llm-worker => llm-engine}/src/llm_client/auth.rs (95%) rename crates/{llm-worker => llm-engine}/src/llm_client/capability.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/client.rs (98%) rename crates/{llm-worker => llm-engine}/src/llm_client/error.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/event.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/mod.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/retry.rs (95%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/anthropic/capability.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/anthropic/events.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/anthropic/mod.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/anthropic/request.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/anthropic/scheme_impl.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/gemini/capability.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/gemini/events.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/gemini/mod.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/gemini/request.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/gemini/scheme_impl.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/mod.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_chat/capability.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_chat/events.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_chat/mod.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_chat/request.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_chat/scheme_impl.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_responses/capability.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_responses/events.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_responses/mod.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_responses/request.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/scheme/openai_responses/scheme_impl.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/transport.rs (100%) rename crates/{llm-worker => llm-engine}/src/llm_client/types.rs (99%) rename crates/{llm-worker => llm-engine}/src/message.rs (100%) rename crates/{llm-worker => llm-engine}/src/prune.rs (98%) rename crates/{llm-worker => llm-engine}/src/state.rs (67%) rename crates/{llm-worker => llm-engine}/src/timeline/event.rs (100%) rename crates/{llm-worker => llm-engine}/src/timeline/mod.rs (100%) rename crates/{llm-worker => llm-engine}/src/timeline/text_block_collector.rs (100%) rename crates/{llm-worker => llm-engine}/src/timeline/thinking_block_collector.rs (100%) rename crates/{llm-worker => llm-engine}/src/timeline/timeline.rs (99%) rename crates/{llm-worker => llm-engine}/src/timeline/tool_call_collector.rs (100%) rename crates/{llm-worker => llm-engine}/src/token_counter.rs (100%) rename crates/{llm-worker => llm-engine}/src/tool.rs (95%) rename crates/{llm-worker => llm-engine}/src/tool_server.rs (97%) rename crates/{llm-worker => llm-engine}/src/usage_record.rs (100%) rename crates/{llm-worker => llm-engine}/tests/anthropic_fixtures.rs (100%) rename crates/{llm-worker => llm-engine}/tests/callback_test.rs (84%) rename crates/{llm-worker => llm-engine}/tests/common/mod.rs (97%) rename crates/{llm-worker => llm-engine}/tests/compile_fail.rs (100%) rename crates/{llm-worker/tests/worker_fixtures.rs => llm-engine/tests/engine_fixtures.rs} (81%) rename crates/{llm-worker/tests/worker_state_test.rs => llm-engine/tests/engine_state_test.rs} (72%) rename crates/{llm-worker => llm-engine}/tests/fixtures/anthropic/anthropic_1767624445.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/anthropic/simple_text.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/anthropic/tool_call.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/gemini/long_text.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/gemini/simple_text.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/gemini/tool_call.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/ollama/long_text.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/ollama/simple_text.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/ollama/tool_call.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/openai/long_text.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/openai/openai_1767708975.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/openai/simple_text.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/fixtures/openai/tool_call.jsonl (100%) rename crates/{llm-worker => llm-engine}/tests/gemini_fixtures.rs (100%) rename crates/{llm-worker => llm-engine}/tests/ollama_fixtures.rs (100%) rename crates/{llm-worker => llm-engine}/tests/openai_fixtures.rs (100%) rename crates/{llm-worker => llm-engine}/tests/parallel_execution_test.rs (88%) rename crates/{llm-worker => llm-engine}/tests/reasoning_round_trip_test.rs (86%) rename crates/{llm-worker => llm-engine}/tests/tool_macro_test.rs (99%) rename crates/{llm-worker => llm-engine}/tests/transport_retry_test.rs (92%) rename crates/{llm-worker => llm-engine}/tests/ui/locked_register_tool.rs (64%) rename crates/{llm-worker => llm-engine}/tests/ui/locked_register_tool.stderr (51%) rename crates/{llm-worker => llm-engine}/tests/ui/tool_server_handle_register_tool.rs (64%) rename crates/{llm-worker => llm-engine}/tests/ui/tool_server_handle_register_tool.stderr (84%) diff --git a/Cargo.lock b/Cargo.lock index 1c90d22f..6b0b57e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2102,7 +2102,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] -name = "llm-worker" +name = "llm-engine" version = "0.2.1" dependencies = [ "async-trait", @@ -2110,7 +2110,7 @@ dependencies = [ "dotenv", "eventsource-stream", "futures", - "llm-worker-macros", + "llm-engine-macros", "reqwest", "schemars", "serde", @@ -2127,7 +2127,7 @@ dependencies = [ ] [[package]] -name = "llm-worker-macros" +name = "llm-engine-macros" version = "0.2.0" dependencies = [ "proc-macro2", @@ -2242,7 +2242,7 @@ name = "manifest" version = "0.1.0" dependencies = [ "arc-swap", - "llm-worker", + "llm-engine", "mlua", "protocol", "secrets", @@ -2373,7 +2373,7 @@ dependencies = [ "chrono", "libc", "lint-common", - "llm-worker", + "llm-engine", "manifest", "schemars", "serde", @@ -2888,7 +2888,7 @@ dependencies = [ "futures-util", "include_dir", "libc", - "llm-worker", + "llm-engine", "manifest", "mcp", "memory", @@ -3045,7 +3045,7 @@ dependencies = [ "async-trait", "base64", "chrono", - "llm-worker", + "llm-engine", "manifest", "reqwest", "secrets", @@ -3901,7 +3901,7 @@ version = "0.1.0" dependencies = [ "async-trait", "futures", - "llm-worker", + "llm-engine", "protocol", "serde", "serde_json", @@ -4352,7 +4352,7 @@ dependencies = [ "async-trait", "chrono", "fs4", - "llm-worker", + "llm-engine", "project-record", "schemars", "serde", @@ -4535,7 +4535,7 @@ dependencies = [ "grep-searcher", "html5ever", "ignore", - "llm-worker", + "llm-engine", "manifest", "markup5ever_rcdom", "pdf-extract", @@ -4715,7 +4715,7 @@ dependencies = [ "base64", "client", "crossterm 0.28.1", - "llm-worker", + "llm-engine", "manifest", "minijinja", "pod-registry", diff --git a/Cargo.toml b/Cargo.toml index 044d3131..bfdf80a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,8 @@ resolver = "2" members = [ "crates/client", - "crates/llm-worker", - "crates/llm-worker-macros", + "crates/llm-engine", + "crates/llm-engine-macros", "crates/session-store", "crates/secrets", "crates/manifest", @@ -29,8 +29,8 @@ members = [ ] default-members = [ "crates/client", - "crates/llm-worker", - "crates/llm-worker-macros", + "crates/llm-engine", + "crates/llm-engine-macros", "crates/session-store", "crates/secrets", "crates/manifest", @@ -61,8 +61,8 @@ license = "MIT" [workspace.dependencies] # Internal crates client = { path = "crates/client" } -llm-worker = { path = "crates/llm-worker", version = "0.2" } -llm-worker-macros = { path = "crates/llm-worker-macros", version = "0.2" } +llm-engine = { path = "crates/llm-engine", version = "0.2" } +llm-engine-macros = { path = "crates/llm-engine-macros", version = "0.2" } manifest = { path = "crates/manifest" } mcp = { path = "crates/mcp" } lint-common = { path = "crates/lint-common" } diff --git a/crates/client/README.md b/crates/client/README.md index 25e4ea08..9e9e9cbd 100644 --- a/crates/client/README.md +++ b/crates/client/README.md @@ -18,7 +18,7 @@ Does not own: - product command names (`yoi`) - Pod state authority (`pod`, `pod-store`, `session-store`) - UI rendering (`tui`) -- Worker turn semantics (`llm-worker`) +- Engine turn semantics (`llm-engine`) ## Design notes diff --git a/crates/llm-worker-macros/Cargo.toml b/crates/llm-engine-macros/Cargo.toml similarity index 74% rename from crates/llm-worker-macros/Cargo.toml rename to crates/llm-engine-macros/Cargo.toml index 72e74d25..d4f924c1 100644 --- a/crates/llm-worker-macros/Cargo.toml +++ b/crates/llm-engine-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "llm-worker-macros" -description = "llm-worker's proc macros" +name = "llm-engine-macros" +description = "llm-engine's proc macros" version = "0.2.0" edition.workspace = true license.workspace = true diff --git a/crates/llm-worker-macros/README.md b/crates/llm-engine-macros/README.md similarity index 88% rename from crates/llm-worker-macros/README.md rename to crates/llm-engine-macros/README.md index 9bbc11ae..94f4c2c1 100644 --- a/crates/llm-worker-macros/README.md +++ b/crates/llm-engine-macros/README.md @@ -1,8 +1,8 @@ -# llm-worker-macros +# llm-engine-macros ## Role -`llm-worker-macros` provides procedural macros for declaring Rust methods as LLM-callable tools. +`llm-engine-macros` provides procedural macros for declaring Rust methods as LLM-callable tools. ## Boundaries diff --git a/crates/llm-worker-macros/src/lib.rs b/crates/llm-engine-macros/src/lib.rs similarity index 94% rename from crates/llm-worker-macros/src/lib.rs rename to crates/llm-engine-macros/src/lib.rs index 2c8b8812..34b17165 100644 --- a/crates/llm-worker-macros/src/lib.rs +++ b/crates/llm-engine-macros/src/lib.rs @@ -1,4 +1,4 @@ -//! llm-worker-macros - Procedural macros for Tool generation +//! llm-engine-macros - Procedural macros for Tool generation //! //! Provides `#[tool_registry]` and `#[tool]` macros to //! automatically generate `Tool` trait implementations from user-defined methods. @@ -215,7 +215,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2:: quote! { match result { Ok(val) => Ok(format!("{:?}", val).into()), - Err(e) => Err(::llm_worker::tool::ToolError::ExecutionFailed(format!("{}", e))), + Err(e) => Err(::llm_engine::tool::ToolError::ExecutionFailed(format!("{}", e))), } } } else { @@ -252,7 +252,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2:: } else { quote! { let args: #args_struct_name = serde_json::from_str(input_json) - .map_err(|e| ::llm_worker::tool::ToolError::InvalidArgument(e.to_string()))?; + .map_err(|e| ::llm_engine::tool::ToolError::InvalidArgument(e.to_string()))?; let result = #method_call #awaiter; #result_handling @@ -268,23 +268,23 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2:: } #[async_trait::async_trait] - impl ::llm_worker::tool::Tool for #tool_struct_name { - async fn execute(&self, input_json: &str, ctx: ::llm_worker::tool::ToolExecutionContext) -> Result<::llm_worker::tool::ToolOutput, ::llm_worker::tool::ToolError> { + impl ::llm_engine::tool::Tool for #tool_struct_name { + async fn execute(&self, input_json: &str, ctx: ::llm_engine::tool::ToolExecutionContext) -> Result<::llm_engine::tool::ToolOutput, ::llm_engine::tool::ToolError> { let _ = &ctx; #execute_body } } impl #self_ty { - /// Get ToolDefinition (for registering with Worker) - pub fn #definition_name(&self) -> ::llm_worker::tool::ToolDefinition { + /// Get ToolDefinition (for registering with Engine) + pub fn #definition_name(&self) -> ::llm_engine::tool::ToolDefinition { let ctx = self.clone(); ::std::sync::Arc::new(move || { let schema = schemars::schema_for!(#args_struct_name); - let meta = ::llm_worker::tool::ToolMeta::new(#tool_name) + let meta = ::llm_engine::tool::ToolMeta::new(#tool_name) .description(#description) .input_schema(serde_json::to_value(schema).unwrap_or(serde_json::json!({}))); - let tool: ::std::sync::Arc = + let tool: ::std::sync::Arc = ::std::sync::Arc::new(#tool_struct_name { ctx: ctx.clone() }); (meta, tool) }) diff --git a/crates/llm-worker/Cargo.toml b/crates/llm-engine/Cargo.toml similarity index 93% rename from crates/llm-worker/Cargo.toml rename to crates/llm-engine/Cargo.toml index fcc29439..c588e268 100644 --- a/crates/llm-worker/Cargo.toml +++ b/crates/llm-engine/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "llm-worker" +name = "llm-engine" description = "A library for building autonomous LLM-powered systems" version = "0.2.1" edition.workspace = true @@ -17,7 +17,7 @@ tokio-util = "0.7" reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "native-tls", "http2"] } eventsource-stream = "0.2" zstd = "0.13" -llm-worker-macros = { workspace = true } +llm-engine-macros = { workspace = true } [dev-dependencies] clap = { version = "4.5", features = ["derive", "env"] } diff --git a/crates/llm-worker/README.md b/crates/llm-engine/README.md similarity index 78% rename from crates/llm-worker/README.md rename to crates/llm-engine/README.md index bc49e83f..e75d1c57 100644 --- a/crates/llm-worker/README.md +++ b/crates/llm-engine/README.md @@ -1,17 +1,17 @@ -# llm-worker +# llm-engine ## Role -`llm-worker` owns provider-independent model turn orchestration over committed history, tools, callbacks, retries, continuation, pruning, and compaction boundaries. +`llm-engine` owns provider-independent model turn orchestration over committed history, tools, callbacks, retries, continuation, pruning, and compaction boundaries. ## Boundaries Owns: -- Worker history mutation and append contracts +- Engine history mutation and append contracts - tool-call loop semantics - pre-stream retry and stream-started continuation policy -- pruning/compaction coordination from the Worker perspective +- pruning/compaction coordination from the Engine perspective - provider-neutral events/callbacks/interceptors Does not own: @@ -23,7 +23,7 @@ Does not own: ## Design notes -The Worker is where turn lifecycle belongs because it sees history, in-flight usage, partial output, and tool-call state. It should not receive context-only volatile facts; model-affecting inputs must first be appended to history. +The Engine is where turn lifecycle belongs because it sees history, in-flight usage, partial output, and tool-call state. It should not receive context-only volatile facts; model-affecting inputs must first be appended to history. ## See also diff --git a/crates/llm-worker/docs/architecture.md b/crates/llm-engine/docs/architecture.md similarity index 90% rename from crates/llm-worker/docs/architecture.md rename to crates/llm-engine/docs/architecture.md index 920e917d..b016f921 100644 --- a/crates/llm-worker/docs/architecture.md +++ b/crates/llm-engine/docs/architecture.md @@ -1,12 +1,12 @@ -# llm-worker アーキテクチャ +# llm-engine アーキテクチャ ## 概要 -llm-workerは3層構成でLLMとのインタラクションを管理する。 +llm-engineは3層構成でLLMとのインタラクションを管理する。 ``` ┌─────────────────────────────────────────┐ -│ Worker (オーケストレーション) │ +│ Engine (オーケストレーション) │ │ ターンループ / フック / ツール実行 │ │ Type-state: Mutable ↔ CacheLocked │ └───────────┬─────────────────────────────┘ @@ -27,7 +27,7 @@ llm-workerは3層構成でLLMとのインタラクションを管理する。 | モジュール | 責務 | 要件 | |---|---|---| -| `worker` | ターンループ、フック統合、ツール実行、Pause/Resume | R1, R4 | +| `engine` | ターンループ、フック統合、ツール実行、Pause/Resume | R1, R4 | | `state` | Type-state (Mutable/CacheLocked) | R2 | | `hook` | Hook trait、10フックポイント | R3, R4 | | `tool` / `tool_server` | ツール定義・登録・実行 | R3 | @@ -42,7 +42,7 @@ llm-workerは3層構成でLLMとのインタラクションを管理する。 ### リクエスト(送信) ``` -Worker.history (Vec) +Engine.history (Vec) → build_request() → Request { items, tools, config } → Scheme.build_request() → プロバイダ固有JSON → Provider.stream() → HTTP POST @@ -55,7 +55,7 @@ HTTP SSE bytes → Scheme.parse_event() → Event (統一型) → Timeline.dispatch() → Handler.on_event() → TextBlockCollector / ToolCallCollector - → Worker: 履歴に追加、ツール実行判定 + → Engine: 履歴に追加、ツール実行判定 ``` ## 内部型 diff --git a/crates/llm-worker/docs/requirements.md b/crates/llm-engine/docs/requirements.md similarity index 72% rename from crates/llm-worker/docs/requirements.md rename to crates/llm-engine/docs/requirements.md index 1d1370d1..d0f9909c 100644 --- a/crates/llm-worker/docs/requirements.md +++ b/crates/llm-engine/docs/requirements.md @@ -1,4 +1,4 @@ -# llm-worker 要件 +# llm-engine 要件 ## 前提 @@ -12,23 +12,23 @@ c. ツール・フックの基本的なスキーマ自動化を提供する メッセージの送信と生成のResume、一時停止/再開。 -- `Worker::run()` でターンを開始 +- `Engine::run()` でターンを開始 - フックから `Pause` を返してターンを一時停止 -- `Worker::resume()` でユーザーメッセージを追加せず継続 +- `Engine::resume()` でユーザーメッセージを追加せず継続 - AIは中断を認識せず、継続として処理する -**実装**: `worker.rs` — `resume()`, `get_pending_tool_calls()`, `WorkerResult::Paused` +**実装**: `engine.rs` — `resume()`, `get_pending_tool_calls()`, `EngineResult::Paused` ### R2: 暗黙的KVキャッシュ保証 キャッシュを破壊しうる操作を明示的にブロックせずとも、いつの間にかキャッシュ破壊してた状態にはしたくない。 - Type-stateパターン(`Mutable` / `CacheLocked`)でコンパイル時に保証 -- `Worker::lock()` でCacheLocked状態に遷移 +- `Engine::lock()` でCacheLocked状態に遷移 - CacheLocked状態ではシステムプロンプトや履歴の変更APIが型レベルで利用不可 - `locked_prefix_len` でプレフィックスの不変性を追跡 -**実装**: `state.rs` (sealed trait), `worker.rs` (state-specific impl blocks) +**実装**: `state.rs` (sealed trait), `engine.rs` (state-specific impl blocks) ### R3: ツール・フックスキーマ自動化 @@ -36,13 +36,13 @@ c. ツール・フックの基本的なスキーマ自動化を提供する - `#[tool_registry]` マクロでツールサーバーを自動構成 - `Hook` traitで10種のフックポイント -**実装**: `llm-worker-macros/`, `tool.rs`, `tool_server.rs`, `hook.rs` +**実装**: `llm-engine-macros/`, `tool.rs`, `tool_server.rs`, `hook.rs` ### R4: フックは上層の関心事 -フックはLLMクライアント層ではなく、Worker(オーケストレーション)層に配置する。 +フックはLLMクライアント層ではなく、Engine(オーケストレーション)層に配置する。 - LLMクライアント (`llm_client/`) はストリーミングとプロトコルのみ -- Worker層でフック実行、ツール統合、Pause/Resume制御 +- Engine層でフック実行、ツール統合、Pause/Resume制御 -**実装**: `worker.rs` (hook integration), `hook.rs` (trait definitions) +**実装**: `engine.rs` (hook integration), `hook.rs` (trait definitions) diff --git a/crates/llm-worker/examples/worker_cancel_demo.rs b/crates/llm-engine/examples/engine_cancel_demo.rs similarity index 69% rename from crates/llm-worker/examples/worker_cancel_demo.rs rename to crates/llm-engine/examples/engine_cancel_demo.rs index 1983f555..6ec75c5a 100644 --- a/crates/llm-worker/examples/worker_cancel_demo.rs +++ b/crates/llm-engine/examples/engine_cancel_demo.rs @@ -1,10 +1,10 @@ -//! Worker cancellation demo +//! Engine cancellation demo //! //! Example of cancelling from another thread during streaming -use llm_worker::llm_client::scheme::{Scheme, anthropic::AnthropicScheme}; -use llm_worker::llm_client::transport::{HttpTransport, ResolvedAuth}; -use llm_worker::{Worker, WorkerResult}; +use llm_engine::llm_client::scheme::{Scheme, anthropic::AnthropicScheme}; +use llm_engine::llm_client::transport::{HttpTransport, ResolvedAuth}; +use llm_engine::{Engine, EngineResult}; use std::time::Duration; #[tokio::main] @@ -28,29 +28,29 @@ async fn main() -> Result<(), Box> { let cap = scheme.default_capability(); let base_url = scheme.default_base_url().to_string(); let client = HttpTransport::new(scheme, model, base_url, ResolvedAuth::ApiKey(api_key), cap); - let worker = Worker::new(client); + let engine = Engine::new(client); - println!("🚀 Starting Worker..."); + println!("🚀 Starting Engine..."); println!("💡 Will cancel after 2 seconds\n"); // Get cancel sender before run (Mutable state) - let cancel_tx = worker.cancel_sender(); + let cancel_tx = engine.cancel_sender(); // Task: Cancel after 2 seconds tokio::spawn(async move { tokio::time::sleep(Duration::from_secs(2)).await; - println!("\n🛑 Cancelling worker..."); + println!("\n🛑 Cancelling engine..."); let _ = cancel_tx.send(()).await; }); println!("📡 Sending request to LLM..."); - match worker.run("Tell me a very long story about a brave knight. Make it as detailed as possible with many paragraphs.").await { + match engine.run("Tell me a very long story about a brave knight. Make it as detailed as possible with many paragraphs.").await { Ok(out) => match out.result { - WorkerResult::Finished => println!("✅ Task completed normally"), - WorkerResult::Paused => println!("⏸️ Task paused"), - WorkerResult::LimitReached => println!("🔒 Turn limit reached"), - WorkerResult::Yielded => println!("↩️ Task yielded"), + EngineResult::Finished => println!("✅ Task completed normally"), + EngineResult::Paused => println!("⏸️ Task paused"), + EngineResult::LimitReached => println!("🔒 Turn limit reached"), + EngineResult::Yielded => println!("↩️ Task yielded"), }, Err(e) => { println!("❌ Task error: {}", e); diff --git a/crates/llm-worker/examples/worker_cli.rs b/crates/llm-engine/examples/engine_cli.rs similarity index 93% rename from crates/llm-worker/examples/worker_cli.rs rename to crates/llm-engine/examples/engine_cli.rs index 5f692f98..8facc5f1 100644 --- a/crates/llm-worker/examples/worker_cli.rs +++ b/crates/llm-engine/examples/engine_cli.rs @@ -1,4 +1,4 @@ -//! Interactive CLI client using Worker +//! Interactive CLI client using Engine //! //! A CLI application for interacting with multiple LLM providers (Anthropic, Gemini, OpenAI, Ollama). //! Demonstrates tool registration and execution, and streaming response display. @@ -12,22 +12,22 @@ //! echo "OPENAI_API_KEY=your-api-key" >> .env //! //! # Anthropic (default) -//! cargo run --example worker_cli +//! cargo run --example engine_cli //! //! # Gemini -//! cargo run --example worker_cli -- --provider gemini +//! cargo run --example engine_cli -- --provider gemini //! //! # OpenAI -//! cargo run --example worker_cli -- --provider openai --model gpt-4o +//! cargo run --example engine_cli -- --provider openai --model gpt-4o //! //! # Ollama (local) -//! cargo run --example worker_cli -- --provider ollama --model llama3.2 +//! cargo run --example engine_cli -- --provider ollama --model llama3.2 //! //! # With options -//! cargo run --example worker_cli -- --provider anthropic --model claude-3-haiku-20240307 --system "You are a helpful assistant." +//! cargo run --example engine_cli -- --provider anthropic --model claude-3-haiku-20240307 --system "You are a helpful assistant." //! //! # Show help -//! cargo run --example worker_cli -- --help +//! cargo run --example engine_cli -- --help //! ``` use std::collections::HashMap; @@ -39,8 +39,8 @@ use tracing::info; use tracing_subscriber::EnvFilter; use clap::{Parser, ValueEnum}; -use llm_worker::{ - Worker, +use llm_engine::{ + Engine, interceptor::{Interceptor, PostToolAction, ToolResultInfo}, llm_client::{ LlmClient, @@ -52,7 +52,7 @@ use llm_worker::{ }, timeline::{Handler, TextBlockEvent, TextBlockKind, ToolUseBlockEvent, ToolUseBlockKind}, }; -use llm_worker_macros::tool_registry; +use llm_engine_macros::tool_registry; // Required imports for macro expansion use schemars; @@ -114,8 +114,8 @@ impl Provider { /// Interactive CLI client supporting multiple LLM providers #[derive(Parser, Debug)] -#[command(name = "worker-cli")] -#[command(about = "Interactive CLI client for multiple LLM providers using Worker")] +#[command(name = "engine-cli")] +#[command(about = "Interactive CLI client for multiple LLM providers using Engine")] #[command(version)] struct Args { /// Provider to use @@ -393,7 +393,7 @@ async fn main() -> Result<(), Box> { dotenv::dotenv().ok(); // Initialize logging - // Use RUST_LOG=debug cargo run --example worker_cli ... for detailed logs + // Use RUST_LOG=debug cargo run --example engine_cli ... for detailed logs // Default is warn level, can be overridden with RUST_LOG environment variable let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn")); @@ -408,7 +408,7 @@ async fn main() -> Result<(), Box> { info!( provider = ?args.provider, model = ?args.model, - "Starting worker CLI" + "Starting engine CLI" ); // Interactive mode or one-shot mode @@ -421,7 +421,7 @@ async fn main() -> Result<(), Box> { .unwrap_or_else(|| args.provider.default_model().to_string()); if is_interactive { - let title = format!("Worker CLI - {}", args.provider.display_name()); + let title = format!("Engine CLI - {}", args.provider.display_name()); let border_len = title.len() + 6; println!("╔{}╗", "═".repeat(border_len)); println!("║ {} ║", title); @@ -453,34 +453,34 @@ async fn main() -> Result<(), Box> { } }; - // Create Worker - let mut worker = Worker::new(client); + // Create Engine + let mut engine = Engine::new(client); let tool_call_names = Arc::new(Mutex::new(HashMap::new())); // Set system prompt if let Some(ref system_prompt) = args.system { - worker.set_system_prompt(system_prompt); + engine.set_system_prompt(system_prompt); } // Register tools (unless --no-tools) if !args.no_tools { let app = AppContext; - worker.register_tool(app.get_current_time_definition()); - worker.register_tool(app.calculate_definition()); + engine.register_tool(app.get_current_time_definition()); + engine.register_tool(app.calculate_definition()); } // Register streaming display handlers - worker + engine .timeline_mut() .on_text_block(StreamingPrinter::new()) .on_tool_use_block(ToolCallPrinter::new(tool_call_names.clone())); - worker.set_interceptor(ToolResultPrinterPolicy::new(tool_call_names)); + engine.set_interceptor(ToolResultPrinterPolicy::new(tool_call_names)); // One-shot mode if let Some(prompt) = args.prompt { - match worker.run(&prompt).await { + match engine.run(&prompt).await { Ok(_) => {} Err(e) => { eprintln!("\n❌ Error: {}", e); @@ -504,8 +504,8 @@ async fn main() -> Result<(), Box> { return Ok(()); } - let mut locked = match worker.run(first_input).await { - Ok(out) => out.worker, + let mut locked = match engine.run(first_input).await { + Ok(out) => out.engine, Err(e) => { eprintln!("\n❌ Error: {}", e); return Ok(()); diff --git a/crates/llm-worker/examples/record_test_fixtures/main.rs b/crates/llm-engine/examples/record_test_fixtures/main.rs similarity index 97% rename from crates/llm-worker/examples/record_test_fixtures/main.rs rename to crates/llm-engine/examples/record_test_fixtures/main.rs index c6262336..485e6669 100644 --- a/crates/llm-worker/examples/record_test_fixtures/main.rs +++ b/crates/llm-engine/examples/record_test_fixtures/main.rs @@ -20,10 +20,10 @@ mod recorder; mod scenarios; use clap::{Parser, ValueEnum}; -use llm_worker::llm_client::scheme::{ +use llm_engine::llm_client::scheme::{ Scheme, anthropic::AnthropicScheme, gemini::GeminiScheme, openai_chat::OpenAIScheme, }; -use llm_worker::llm_client::transport::{HttpTransport, ResolvedAuth}; +use llm_engine::llm_client::transport::{HttpTransport, ResolvedAuth}; fn make_transport(scheme: S, model: &str, auth: ResolvedAuth) -> HttpTransport { let cap = scheme.default_capability(); @@ -225,7 +225,7 @@ async fn main() -> Result<(), Box> { } println!("\n✅ Done!"); - println!("Run tests with: cargo test -p worker"); + println!("Run tests with: cargo test -p engine"); Ok(()) } diff --git a/crates/llm-worker/examples/record_test_fixtures/recorder.rs b/crates/llm-engine/examples/record_test_fixtures/recorder.rs similarity index 96% rename from crates/llm-worker/examples/record_test_fixtures/recorder.rs rename to crates/llm-engine/examples/record_test_fixtures/recorder.rs index 93a9054f..3a422ec2 100644 --- a/crates/llm-worker/examples/record_test_fixtures/recorder.rs +++ b/crates/llm-engine/examples/record_test_fixtures/recorder.rs @@ -8,7 +8,7 @@ use std::path::Path; use std::time::{Instant, SystemTime, UNIX_EPOCH}; use futures::StreamExt; -use llm_worker::llm_client::{LlmClient, Request}; +use llm_engine::llm_client::{LlmClient, Request}; /// Recorded event #[derive(Debug, serde::Serialize, serde::Deserialize)] @@ -79,7 +79,7 @@ pub async fn record_request( } // Save - let fixtures_dir = Path::new("worker/tests/fixtures").join(subdir); + let fixtures_dir = Path::new("engine/tests/fixtures").join(subdir); fs::create_dir_all(&fixtures_dir)?; let filepath = fixtures_dir.join(format!("{}.jsonl", output_name)); diff --git a/crates/llm-worker/examples/record_test_fixtures/scenarios.rs b/crates/llm-engine/examples/record_test_fixtures/scenarios.rs similarity index 97% rename from crates/llm-worker/examples/record_test_fixtures/scenarios.rs rename to crates/llm-engine/examples/record_test_fixtures/scenarios.rs index 6fd80af5..62845bea 100644 --- a/crates/llm-worker/examples/record_test_fixtures/scenarios.rs +++ b/crates/llm-engine/examples/record_test_fixtures/scenarios.rs @@ -2,7 +2,7 @@ //! //! Defines requests and output file names for each scenario -use llm_worker::llm_client::{Request, ToolDefinition}; +use llm_engine::llm_client::{Request, ToolDefinition}; /// Test scenario pub struct TestScenario { diff --git a/crates/llm-worker/src/callback.rs b/crates/llm-engine/src/callback.rs similarity index 97% rename from crates/llm-worker/src/callback.rs rename to crates/llm-engine/src/callback.rs index 644e0178..301a32a5 100644 --- a/crates/llm-worker/src/callback.rs +++ b/crates/llm-engine/src/callback.rs @@ -1,7 +1,7 @@ //! Closure-based event callback API //! //! Provides a closure-based alternative to implementing `Handler` directly. -//! Register callbacks on `Worker` via `on_text_block()`, `on_tool_use_block()`, +//! Register callbacks on `Engine` via `on_text_block()`, `on_tool_use_block()`, //! `on_usage()`, etc. use std::marker::PhantomData; @@ -18,13 +18,13 @@ use crate::tool::ToolCall; /// Callback scope for a text block. /// -/// Passed to the setup closure registered with `Worker::on_text_block()`. +/// Passed to the setup closure registered with `Engine::on_text_block()`. /// Register per-block callbacks via `on_delta()` and `on_stop()`. /// /// # Examples /// /// ```ignore -/// worker.on_text_block(|block| { +/// engine.on_text_block(|block| { /// block.on_delta(|text| print!("{}", text)); /// block.on_stop(|full_text| println!("\n--- {} chars ---", full_text.len())); /// }); @@ -176,13 +176,13 @@ impl Handler for ClosureThinkingBlockHandler { /// Callback scope for a tool use block. /// -/// Passed to the setup closure registered with `Worker::on_tool_use_block()`. +/// Passed to the setup closure registered with `Engine::on_tool_use_block()`. /// The setup closure also receives `&ToolUseBlockStart` with `id` and `name`. /// /// # Examples /// /// ```ignore -/// worker.on_tool_use_block(|start, block| { +/// engine.on_tool_use_block(|start, block| { /// println!("Tool: {} ({})", start.name, start.id); /// block.on_delta(|json| { /* streaming JSON fragment */ }); /// block.on_stop(|call| println!("Done: {}", call.name)); diff --git a/crates/llm-worker/src/worker.rs b/crates/llm-engine/src/engine.rs similarity index 93% rename from crates/llm-worker/src/worker.rs rename to crates/llm-engine/src/engine.rs index 8310bdba..6c13e6b2 100644 --- a/crates/llm-worker/src/worker.rs +++ b/crates/llm-engine/src/engine.rs @@ -22,19 +22,19 @@ use crate::{ ToolDefinition, error::is_retryable, event::Event, retry::RetryPolicy, transport::DEFAULT_FIRST_STREAM_EVENT_TIMEOUT, types::parse_tool_arguments, }, - state::{Locked, Mutable, WorkerState}, + state::{EngineState, Locked, Mutable}, timeline::event::{ErrorEvent, StatusEvent, UsageEvent}, timeline::{TextBlockCollector, ThinkingBlockCollector, Timeline, ToolCallCollector}, tool::{ - ToolCall, ToolDefinition as WorkerToolDefinition, ToolError, ToolExecutionContext, + ToolCall, ToolDefinition as EngineToolDefinition, ToolError, ToolExecutionContext, ToolOutputLimits, ToolResult, truncate_content, }, tool_server::{ToolServer, ToolServerHandle}, }; -/// Worker errors +/// Engine errors #[derive(Debug, thiserror::Error)] -pub enum WorkerError { +pub enum EngineError { /// Client error #[error("Client error: {0}")] Client(#[from] ClientError), @@ -60,17 +60,17 @@ pub enum ToolRegistryError { DuplicateName(String), } -/// Worker configuration +/// Engine configuration #[derive(Debug, Clone, Default)] -pub struct WorkerConfig { +pub struct EngineConfig { // Reserved for future extensions (currently empty) _private: (), } -/// Worker execution result (status) +/// Engine execution result (status) #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] -pub enum WorkerResult { +pub enum EngineResult { /// Completed (waiting for user input) Finished, /// Paused (can be resumed) @@ -85,14 +85,14 @@ pub enum WorkerResult { Yielded, } -/// Result of [`Worker::run()`] / [`Worker::resume()`]. +/// Result of [`Engine::run()`] / [`Engine::resume()`]. /// -/// Contains the `Locked` Worker (ready for subsequent runs) and the outcome. -pub struct RunOutput { - /// The Worker, now in Locked state. - pub worker: Worker, +/// Contains the `Locked` Engine (ready for subsequent runs) and the outcome. +pub struct EngineRunOutput { + /// The Engine, now in Locked state. + pub engine: Engine, /// Outcome of the turn. - pub result: WorkerResult, + pub result: EngineResult, } /// Internal: tool execution result @@ -113,27 +113,27 @@ const MAX_STREAM_CONTINUATIONS: u32 = 3; /// - [`Mutable`]: Initial state. System prompt, history, and tools can be freely edited. /// - [`Locked`]: Cache-protected state. Prefix context is immutable; only `run()` / `resume()` are available. /// -/// Calling `run()` on a `Mutable` Worker consumes it and returns a -/// `Locked` Worker together with the result. This ensures the +/// Calling `run()` on a `Mutable` Engine consumes it and returns a +/// `Locked` Engine together with the result. This ensures the /// cache prefix is fixed for optimal KV cache hit rate. /// /// ```ignore -/// let mut worker = Worker::new(client) +/// let mut engine = Engine::new(client) /// .system_prompt("You are a helpful assistant."); -/// worker.register_tool(my_tool); +/// engine.register_tool(my_tool); /// -/// // Mutable::run() consumes self → RunOutput { worker: Locked, result } -/// let out = worker.run("Hello").await?; -/// let mut worker = out.worker; +/// // Mutable::run() consumes self → EngineRunOutput { engine: Locked, result } +/// let out = engine.run("Hello").await?; +/// let mut engine = out.engine; /// /// // Locked::run() borrows &mut self -/// worker.run("Follow-up").await?; +/// engine.run("Follow-up").await?; /// /// // To edit between turns, unlock back to Mutable -/// let mut worker = worker.unlock(); -/// worker.truncate_history(5); -/// let out = worker.run("Continue").await?; -/// let mut worker = out.worker; +/// let mut engine = engine.unlock(); +/// engine.truncate_history(5); +/// let out = engine.run("Continue").await?; +/// let mut engine = out.engine; /// ``` #[derive(Debug, Clone, PartialEq, Eq)] pub struct LlmRetryNotice { @@ -152,7 +152,7 @@ enum StreamCompletion { Interrupted { reason: String }, } -pub struct Worker { +pub struct Engine { /// LLM client client: C, /// Retry policy for opening an LLM response stream. @@ -172,22 +172,22 @@ pub struct Worker { interceptor: Box, /// System prompt system_prompt: Option, - /// Item history (owned by Worker) + /// Item history (owned by Engine) history: Vec, /// History length at lock time (only meaningful in Locked state) locked_prefix_len: usize, /// AgentTurn count. /// - /// Once retry (`llm-worker-stream-continuation`) is implemented, an + /// Once retry (`llm-engine-stream-continuation`) is implemented, an /// AgentTurn collapses N retried `LlmCall`s with identical input; /// today retry is not implemented so AgentTurn and LlmCall fire 1:1 /// and the increment site (the LLM-call loop) is shared. /// `max_turns` is interpreted as a per-`run()` AgentTurn cap. turn_count: usize, - /// LlmCall count (per-Worker running counter, monotonic). Unlike + /// LlmCall count (per-Engine running counter, monotonic). Unlike /// `turn_count` this never collapses retries. llm_call_count: usize, - /// Tool execution batch count (per-Worker running counter, monotonic). + /// Tool execution batch count (per-Engine running counter, monotonic). /// Each batch corresponds to one collected assistant tool-call set or one /// resumed pending tool-call set. tool_execution_batch_count: usize, @@ -212,7 +212,7 @@ pub struct Worker { /// Pre-stream lifecycle callbacks for debugging stalls before provider /// stream events become visible. lifecycle_trace_cbs: Vec>, - /// Non-fatal warning callbacks. Invoked when the Worker wants to + /// Non-fatal warning callbacks. Invoked when the Engine wants to /// surface an advisory message to the upper layer (e.g. Pod) so it /// can be forwarded to the user — distinct from `tracing::warn!`, /// which is for developer-facing logs. @@ -223,7 +223,7 @@ pub struct Worker { /// enters history. tool_result_cbs: Vec>, /// History-append callbacks. Invoked for non-streamed items when they - /// are appended to persistent worker history, so upper layers can + /// are appended to persistent engine history, so upper layers can /// broadcast those items using history itself as the source of truth. history_append_cbs: Vec>, /// Request configuration (max_tokens, temperature, etc.) @@ -260,7 +260,7 @@ pub struct Worker { _state: PhantomData, } -impl Worker { +impl Engine { fn reset_interruption_state(&mut self) { self.last_run_interrupted = false; } @@ -269,7 +269,7 @@ impl Worker { while self.cancel_rx.try_recv().is_ok() {} } - /// Discard pending cancellation notifications while the worker is idle. + /// Discard pending cancellation notifications while the engine is idle. /// /// Cancellation is a running-turn control signal. Callers that own a higher /// level run state can use this before starting a new turn so an old idle @@ -296,7 +296,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// worker.on_text_block(|block| { + /// engine.on_text_block(|block| { /// block.on_delta(|text| print!("{}", text)); /// block.on_stop(|full_text| println!("\n--- {} chars ---", full_text.len())); /// }); @@ -335,7 +335,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// worker.on_tool_use_block(|start, block| { + /// engine.on_tool_use_block(|start, block| { /// println!("Tool: {} ({})", start.name, start.id); /// block.on_delta(|json| { /* streaming JSON fragment */ }); /// block.on_stop(|call| println!("Done: {}", call.name)); @@ -468,7 +468,7 @@ impl Worker { /// Register a non-fatal warning callback. /// /// The callback is invoked with a short human-readable message - /// whenever the Worker encounters a condition that should be + /// whenever the Engine encounters a condition that should be /// surfaced to a human (e.g. tool output byte-cap truncation). /// This channel is separate from `tracing::warn!`, which remains /// in place for developer logs. @@ -498,7 +498,7 @@ impl Worker { } } - /// Register a callback invoked for items appended directly to worker + /// Register a callback invoked for items appended directly to engine /// history outside streaming timeline callbacks. pub fn on_history_append(&mut self, callback: impl Fn(&Item) + Send + Sync + 'static) { self.history_append_cbs.push(Box::new(callback)); @@ -639,7 +639,7 @@ impl Worker { self.turn_count } - /// Get the current LlmCall count (per-Worker running counter, never + /// Get the current LlmCall count (per-Engine running counter, never /// collapsed by retry). pub fn llm_call_count(&self) -> usize { self.llm_call_count @@ -657,7 +657,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// worker.set_max_tokens(4096); + /// engine.set_max_tokens(4096); /// ``` pub fn set_max_tokens(&mut self, max_tokens: u32) { self.request_config.max_tokens = Some(max_tokens); @@ -671,7 +671,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// worker.set_temperature(0.7); + /// engine.set_temperature(0.7); /// ``` pub fn set_temperature(&mut self, temperature: f32) { self.request_config.temperature = Some(temperature); @@ -682,7 +682,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// worker.set_top_p(0.9); + /// engine.set_top_p(0.9); /// ``` pub fn set_top_p(&mut self, top_p: f32) { self.request_config.top_p = Some(top_p); @@ -695,7 +695,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// worker.set_top_k(40); + /// engine.set_top_k(40); /// ``` pub fn set_top_k(&mut self, top_k: u32) { self.request_config.top_k = Some(top_k); @@ -706,7 +706,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// worker.add_stop_sequence("\n\n"); + /// engine.add_stop_sequence("\n\n"); /// ``` pub fn add_stop_sequence(&mut self, sequence: impl Into) { self.request_config.stop_sequences.push(sequence.into()); @@ -730,23 +730,23 @@ impl Worker { /// Cancel execution /// /// Interrupts currently running streaming or tool execution. - /// WorkerError::Cancelled is returned at the next event loop checkpoint. + /// EngineError::Cancelled is returned at the next event loop checkpoint. /// /// # Examples /// /// ```ignore /// use std::sync::Arc; - /// let worker = Arc::new(Mutex::new(Worker::new(client))); + /// let engine = Arc::new(Mutex::new(Engine::new(client))); /// /// // Run in another thread - /// let worker_clone = worker.clone(); + /// let worker_clone = engine.clone(); /// tokio::spawn(async move { /// let mut w = worker_clone.lock().unwrap(); /// w.run("Long task...").await /// }); /// /// // Cancel - /// worker.lock().unwrap().cancel(); + /// engine.lock().unwrap().cancel(); /// ``` pub fn cancel(&self) { let _ = self.cancel_tx.try_send(()); @@ -849,15 +849,15 @@ impl Worker { /// async fn finalize_interruption( &mut self, - result: Result, - ) -> Result { + result: Result, + ) -> Result { match result { Ok(value) => Ok(value), Err(err) => { self.last_run_interrupted = true; let reason = match &err { - WorkerError::Aborted(reason) => reason.clone(), - WorkerError::Cancelled => "Cancelled".to_string(), + EngineError::Aborted(reason) => reason.clone(), + EngineError::Cancelled => "Cancelled".to_string(), _ => err.to_string(), }; self.interceptor.on_abort(&reason).await; @@ -913,7 +913,7 @@ impl Worker { async fn execute_tools( &mut self, tool_calls: Vec, - ) -> Result { + ) -> Result { use futures::future::join_all; // Map from tool call ID to (ToolCall, Meta, Tool, Context) @@ -953,7 +953,7 @@ impl Worker { } PreToolAction::Abort(reason) => { self.last_run_interrupted = true; - return Err(WorkerError::Aborted(reason)); + return Err(EngineError::Aborted(reason)); } PreToolAction::Pause => { self.last_run_interrupted = true; @@ -1010,7 +1010,7 @@ impl Worker { } self.timeline.abort_current_block(); self.last_run_interrupted = true; - return Err(WorkerError::Cancelled); + return Err(EngineError::Cancelled); } }; results.extend(synthetic_results); @@ -1032,7 +1032,7 @@ impl Worker { PostToolAction::Continue => {} PostToolAction::Abort(reason) => { self.last_run_interrupted = true; - return Err(WorkerError::Aborted(reason)); + return Err(EngineError::Aborted(reason)); } } // Reflect interceptor-modified results @@ -1084,14 +1084,14 @@ impl Worker { } /// Internal turn execution logic - async fn run_turn_loop(&mut self) -> Result { + async fn run_turn_loop(&mut self) -> Result { self.reset_interruption_state(); let tool_definitions = self.build_tool_definitions(); info!( item_count = self.history.len(), tool_count = tool_definitions.len(), - "Starting worker run" + "Starting engine run" ); // Resume pending tool calls from a previous Pause @@ -1109,7 +1109,7 @@ impl Worker { info!("Execution cancelled"); self.timeline.abort_current_block(); self.last_run_interrupted = true; - return Err(WorkerError::Cancelled); + return Err(EngineError::Cancelled); } let current_turn = self.turn_count; @@ -1138,7 +1138,7 @@ impl Worker { // Prune projection: if both the config and the savings // estimator are configured, drop ToolResult.content from // prunable candidates whose estimated savings meet the - // threshold. Worker does not own usage history itself; the + // threshold. Engine does not own usage history itself; the // estimator is injected by the layer that does. if let (Some(config), Some(token_estimator), Some(savings_estimator)) = ( &self.prune_config, @@ -1199,7 +1199,7 @@ impl Worker { cb(current_turn); } self.last_run_interrupted = true; - return Err(WorkerError::Aborted(reason)); + return Err(EngineError::Aborted(reason)); } PreRequestAction::YieldWith(items) => { self.append_history_items(items.clone()); @@ -1209,7 +1209,7 @@ impl Worker { cb(current_turn); } self.last_run_interrupted = true; - return Ok(WorkerResult::Yielded); + return Ok(EngineResult::Yielded); } PreRequestAction::Yield => { info!("Yielded by interceptor"); @@ -1217,7 +1217,7 @@ impl Worker { cb(current_turn); } self.last_run_interrupted = true; - return Ok(WorkerResult::Yielded); + return Ok(EngineResult::Yielded); } PreRequestAction::ContinueWith(items) => { self.append_history_items(items.clone()); @@ -1227,7 +1227,7 @@ impl Worker { } // LlmCall boundary fires per LLM generation request — today - // 1:1 with AgentTurn, but retry (`llm-worker-stream-continuation`) + // 1:1 with AgentTurn, but retry (`llm-engine-stream-continuation`) // will multiply this within a single AgentTurn. let current_llm_call = self.llm_call_count; for cb in &self.llm_call_start_cbs { @@ -1262,7 +1262,7 @@ impl Worker { stream_continuations += 1; if stream_continuations > MAX_STREAM_CONTINUATIONS { self.last_run_interrupted = true; - return Err(WorkerError::Client(ClientError::Api { + return Err(EngineError::Client(ClientError::Api { status: None, code: None, message: format!("LLM stream interrupted too many times: {reason}"), @@ -1315,7 +1315,7 @@ impl Worker { match self.interceptor.on_turn_end(&self.history).await { TurnEndAction::Finish => { self.last_run_interrupted = false; - return Ok(WorkerResult::Finished); + return Ok(EngineResult::Finished); } TurnEndAction::ContinueWithMessages(additional) => { self.append_history_items(additional); @@ -1323,7 +1323,7 @@ impl Worker { } TurnEndAction::Pause => { self.last_run_interrupted = true; - return Ok(WorkerResult::Paused); + return Ok(EngineResult::Paused); } } } @@ -1340,7 +1340,7 @@ impl Worker { "Turn limit reached" ); self.last_run_interrupted = false; - return Ok(WorkerResult::LimitReached); + return Ok(EngineResult::LimitReached); } } } @@ -1351,7 +1351,7 @@ impl Worker { request: Request, turn: usize, llm_call: usize, - ) -> Result { + ) -> Result { let policy = self.retry_policy.clone(); let started = Instant::now(); let mut failed_attempt: u32 = 0; @@ -1385,7 +1385,7 @@ impl Worker { ); self.timeline.abort_current_block(); self.last_run_interrupted = true; - return Err(WorkerError::Cancelled); + return Err(EngineError::Cancelled); } }; @@ -1417,7 +1417,7 @@ impl Worker { ); self.timeline.abort_current_block(); self.last_run_interrupted = true; - return Err(WorkerError::Cancelled); + return Err(EngineError::Cancelled); } }; match first_event_result { @@ -1459,7 +1459,7 @@ impl Worker { let next_failed_attempt = failed_attempt + 1; if next_failed_attempt >= policy.max_attempts || !is_retryable(&err) { self.last_run_interrupted = true; - return Err(WorkerError::Client(err)); + return Err(EngineError::Client(err)); } let wait = err @@ -1468,7 +1468,7 @@ impl Worker { let elapsed = started.elapsed(); if elapsed + wait > policy.total_timeout { self.last_run_interrupted = true; - return Err(WorkerError::Client(err)); + return Err(EngineError::Client(err)); } warn!( @@ -1497,7 +1497,7 @@ impl Worker { } self.timeline.abort_current_block(); self.last_run_interrupted = true; - return Err(WorkerError::Cancelled); + return Err(EngineError::Cancelled); } } @@ -1511,7 +1511,7 @@ impl Worker { request: Request, turn: usize, llm_call: usize, - ) -> Result { + ) -> Result { debug!( item_count = request.items.len(), tool_count = request.tools.len(), @@ -1561,7 +1561,7 @@ impl Worker { self.timeline.abort_current_block(); self.timeline.flush_usage(); self.last_run_interrupted = true; - return Err(WorkerError::Client(ClientError::Api { + return Err(EngineError::Client(ClientError::Api { status: None, code: err.code.clone(), message: err.message.clone(), @@ -1579,7 +1579,7 @@ impl Worker { self.timeline.abort_current_block(); self.timeline.flush_usage(); self.last_run_interrupted = true; - return Err(WorkerError::Cancelled); + return Err(EngineError::Cancelled); } } } @@ -1595,11 +1595,11 @@ impl Worker { async fn execute_and_commit_tools( &mut self, tool_calls: Vec, - ) -> Result, WorkerError> { + ) -> Result, EngineError> { match self.execute_tools(tool_calls).await { Ok(ToolExecutionResult::Paused) => { self.last_run_interrupted = true; - Ok(Some(WorkerResult::Paused)) + Ok(Some(EngineResult::Paused)) } Ok(ToolExecutionResult::Completed(results)) => { // Route per-result pushes through the callback path so @@ -1624,8 +1624,8 @@ impl Worker { } } -impl Worker { - /// Create a new Worker (in Mutable state) +impl Engine { + /// Create a new Engine (in Mutable state) pub fn new(client: C) -> Self { let text_block_collector = TextBlockCollector::new(); let tool_call_collector = ToolCallCollector::new(); @@ -1684,13 +1684,13 @@ impl Worker { /// /// The factory is queued and executed at the next `run()` or `resume()` call. /// Duplicate name detection occurs at that point and surfaces as - /// [`WorkerError::ToolRegistry`]. - pub fn register_tool(&mut self, factory: WorkerToolDefinition) { + /// [`EngineError::ToolRegistry`]. + pub fn register_tool(&mut self, factory: EngineToolDefinition) { self.tool_server.register_tool(factory); } /// Register multiple tool factories for deferred initialization. - pub fn register_tools(&mut self, factories: impl IntoIterator) { + pub fn register_tools(&mut self, factories: impl IntoIterator) { self.tool_server.register_tools(factories); } @@ -1719,7 +1719,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// let worker = Worker::new(client) + /// let engine = Engine::new(client) /// .system_prompt("You are a helpful assistant.") /// .max_tokens(4096); /// ``` @@ -1733,7 +1733,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// let worker = Worker::new(client) + /// let engine = Engine::new(client) /// .temperature(0.7); /// ``` pub fn temperature(mut self, temperature: f32) -> Self { @@ -1768,7 +1768,7 @@ impl Worker { /// .with_max_tokens(4096) /// .with_temperature(0.7); /// - /// let worker = Worker::new(client) + /// let engine = Engine::new(client) /// .system_prompt("...") /// .with_config(config); /// ``` @@ -1791,7 +1791,7 @@ impl Worker { /// # Examples /// /// ```ignore - /// let worker = Worker::new(client) + /// let engine = Engine::new(client) /// .temperature(0.7) /// .top_k(40) /// .validate()?; // Error if using OpenAI since top_k is not supported @@ -1799,13 +1799,13 @@ impl Worker { /// /// # Returns /// * `Ok(Self)` - Validation successful - /// * `Err(WorkerError::ConfigWarnings)` - Has unsupported settings - pub fn validate(self) -> Result { + /// * `Err(EngineError::ConfigWarnings)` - Has unsupported settings + pub fn validate(self) -> Result { let warnings = self.client.validate_config(&self.request_config); if warnings.is_empty() { Ok(self) } else { - Err(WorkerError::ConfigWarnings(warnings)) + Err(EngineError::ConfigWarnings(warnings)) } } @@ -1820,7 +1820,7 @@ impl Worker { /// Append items to history and notify history-append observers for each /// item before it lands. This is the only public Mutable-state API for - /// growing worker history; callers that need session-log persistence must + /// growing engine history; callers that need session-log persistence must /// install [`on_history_append`](Self::on_history_append) before calling it. pub fn append_history(&mut self, items: impl IntoIterator) { self.append_history_items(items); @@ -1855,7 +1855,7 @@ impl Worker { /// Apply configuration (reserved for future extensions) #[allow(dead_code)] - pub fn config(self, _config: WorkerConfig) -> Self { + pub fn config(self, _config: EngineConfig) -> Self { self } @@ -1864,13 +1864,16 @@ impl Worker { /// This is the primary entry point for first use. Equivalent to /// `self.lock()` followed by `locked.run(user_input)`. /// - /// Subsequent runs can use [`Worker::run()`] directly. - /// To edit state between turns, call [`unlock()`](Worker::unlock) first. - pub async fn run(self, user_input: impl Into) -> Result, WorkerError> { + /// Subsequent runs can use [`Engine::run()`] directly. + /// To edit state between turns, call [`unlock()`](Engine::unlock) first. + pub async fn run( + self, + user_input: impl Into, + ) -> Result, EngineError> { let mut locked = self.lock(); let result = locked.run(user_input).await?; - Ok(RunOutput { - worker: locked, + Ok(EngineRunOutput { + engine: locked, result, }) } @@ -1878,11 +1881,11 @@ impl Worker { /// Resume from Paused, consuming self and transitioning to Locked. /// /// Used after `unlock()` → edit → resume. - pub async fn resume(self) -> Result, WorkerError> { + pub async fn resume(self) -> Result, EngineError> { let mut locked = self.lock(); let result = locked.resume().await?; - Ok(RunOutput { - worker: locked, + Ok(EngineRunOutput { + engine: locked, result, }) } @@ -1895,15 +1898,15 @@ impl Worker { /// /// Most callers should use [`run()`](Self::run) instead, which calls /// this internally. Use `lock()` directly only when you need the - /// `Locked` worker back on error (e.g. in a persistence layer). + /// `Locked` engine back on error (e.g. in a persistence layer). /// /// # Panics /// /// Panics if a pending tool factory produces a duplicate name. - pub fn lock(self) -> Worker { + pub fn lock(self) -> Engine { self.tool_server.flush_pending(); let locked_prefix_len = self.history.len(); - Worker { + Engine { client: self.client, retry_policy: self.retry_policy, timeline: self.timeline, @@ -1947,7 +1950,7 @@ impl Worker { } } -impl Worker { +impl Engine { /// Execute a turn /// /// Adds a new user message to history and sends a request to the LLM. @@ -1955,7 +1958,7 @@ impl Worker { pub async fn run( &mut self, user_input: impl Into, - ) -> Result { + ) -> Result { self.reset_interruption_state(); // Interceptor: on_prompt_submit let mut user_item = Item::user_message(user_input); @@ -1963,7 +1966,7 @@ impl Worker { PromptAction::Cancel(reason) => { self.last_run_interrupted = true; return self - .finalize_interruption(Err(WorkerError::Aborted(reason))) + .finalize_interruption(Err(EngineError::Aborted(reason))) .await; } PromptAction::Continue => Vec::new(), @@ -1980,7 +1983,7 @@ impl Worker { /// Resume execution (from Paused state) /// /// Resumes turn processing from current state without adding a new user message. - pub async fn resume(&mut self) -> Result { + pub async fn resume(&mut self) -> Result { self.reset_interruption_state(); let result = self.run_turn_loop().await; self.finalize_interruption(result).await @@ -1995,8 +1998,8 @@ impl Worker { /// /// Note: After this operation, subsequent requests may not hit the cache. /// Use only when you need to edit history. - pub fn unlock(self) -> Worker { - Worker { + pub fn unlock(self) -> Engine { + Engine { client: self.client, retry_policy: self.retry_policy, timeline: self.timeline, diff --git a/crates/llm-worker/src/event.rs b/crates/llm-engine/src/event.rs similarity index 73% rename from crates/llm-worker/src/event.rs rename to crates/llm-engine/src/event.rs index cb54a785..1a66709d 100644 --- a/crates/llm-worker/src/event.rs +++ b/crates/llm-engine/src/event.rs @@ -1,4 +1,4 @@ -//! Public event types for Worker layer +//! Public event types for Engine layer //! //! Re-exports from the canonical event definitions in llm_client. diff --git a/crates/llm-worker/src/handler.rs b/crates/llm-engine/src/handler.rs similarity index 98% rename from crates/llm-worker/src/handler.rs rename to crates/llm-engine/src/handler.rs index b6928800..538a66f2 100644 --- a/crates/llm-worker/src/handler.rs +++ b/crates/llm-engine/src/handler.rs @@ -32,7 +32,7 @@ pub trait Kind { /// # Examples /// /// ```ignore -/// use llm_worker::timeline::{Handler, TextBlockEvent, TextBlockKind}; +/// use llm_engine::timeline::{Handler, TextBlockEvent, TextBlockKind}; /// /// struct TextCollector { /// texts: Vec, diff --git a/crates/llm-worker/src/interceptor.rs b/crates/llm-engine/src/interceptor.rs similarity index 89% rename from crates/llm-worker/src/interceptor.rs rename to crates/llm-engine/src/interceptor.rs index 0cb926fc..ecfb83cb 100644 --- a/crates/llm-worker/src/interceptor.rs +++ b/crates/llm-engine/src/interceptor.rs @@ -1,8 +1,8 @@ -//! Interceptor - control flow delegation for the Worker execution loop +//! Interceptor - control flow delegation for the Engine execution loop //! //! Defines the [`Interceptor`] trait that upper layers (e.g. Pod) implement //! to inject orchestration decisions (approval, skip, pause, abort) -//! into the Worker's turn loop without the Worker knowing about +//! into the Engine's turn loop without the Engine knowing about //! higher-level concepts. use std::sync::Arc; @@ -36,13 +36,13 @@ pub enum PromptAction { pub enum PreRequestAction { /// Proceed normally. Continue, - /// Proceed after appending these items to durable worker history. + /// Proceed after appending these items to durable engine history. /// /// This is for upper-layer budget/status nudges that the model may react /// to: the items are committed before the request so later turns can see - /// why the worker changed course. + /// why the engine changed course. ContinueWith(Vec), - /// Yield after appending these items to durable worker history. + /// Yield after appending these items to durable engine history. /// /// This is for host-mediated pre-request appends that must be visible to /// usage accounting and compaction checks before the current LLM request is @@ -52,7 +52,7 @@ pub enum PreRequestAction { Cancel(String), /// Yield control to the caller for external processing. /// - /// The Worker exits the turn loop cleanly with `WorkerResult::Yielded`. + /// The Engine exits the turn loop cleanly with `EngineResult::Yielded`. /// The caller is expected to resume execution later. Yield, } @@ -129,9 +129,9 @@ pub struct ToolResultInfo { // Interceptor Trait // ============================================================================= -/// Intercepts the Worker execution loop at key decision points. +/// Intercepts the Engine execution loop at key decision points. /// -/// All methods have default implementations that let the Worker +/// All methods have default implementations that let the Engine /// proceed without intervention. Upper layers (e.g. Pod) provide /// richer implementations for approval flows, permission checks, etc. #[async_trait] @@ -141,7 +141,7 @@ pub trait Interceptor: Send + Sync { PromptAction::Continue } - /// Items that should be **committed to `worker.history`** just + /// Items that should be **committed to `engine.history`** just /// before the next LLM request. Returned items are `extend`ed into /// the persistent history (and therefore picked up by the per-turn /// clone that backs the LLM request, plus the usual @@ -164,12 +164,12 @@ pub trait Interceptor: Send + Sync { } /// Called before each LLM request. The context starts as a clone - /// of `worker.history` (after `pending_history_appends` and the - /// Worker's own prune projection have been applied). + /// of `engine.history` (after `pending_history_appends` and the + /// Engine's own prune projection have been applied). /// /// Direct mutations to `context` remain request-local and are not persisted. /// If an interceptor derives a human/model-visible nudge from the current - /// request context, return [`PreRequestAction::ContinueWith`] so the Worker + /// request context, return [`PreRequestAction::ContinueWith`] so the Engine /// commits it to history before the request is sent. async fn pre_llm_request(&self, _context: &mut Vec) -> PreRequestAction { PreRequestAction::Continue @@ -194,7 +194,7 @@ pub trait Interceptor: Send + Sync { async fn on_abort(&self, _reason: &str) {} } -/// Default interceptor: no intervention. Worker proceeds through the loop +/// Default interceptor: no intervention. Engine proceeds through the loop /// without any external control flow decisions. pub(crate) struct DefaultInterceptor; diff --git a/crates/llm-worker/src/lib.rs b/crates/llm-engine/src/lib.rs similarity index 65% rename from crates/llm-worker/src/lib.rs rename to crates/llm-engine/src/lib.rs index 535cfc7b..02766e91 100644 --- a/crates/llm-worker/src/lib.rs +++ b/crates/llm-engine/src/lib.rs @@ -1,28 +1,28 @@ -//! llm-worker - LLM Worker Library +//! llm-engine - LLM Engine Library //! //! Provides components for managing interactions with LLMs. //! //! # Main Components //! -//! - [`Worker`] - Central component for managing LLM interactions +//! - [`Engine`] - Central component for managing LLM interactions //! - [`tool::Tool`] - Tools that can be invoked by the LLM //! - [`interceptor::Interceptor`] - Control-flow delegation for the execution loop -//! - Closure-based event callbacks via `Worker::on_text_block()`, `on_tool_use_block()`, etc. +//! - Closure-based event callbacks via `Engine::on_text_block()`, `on_tool_use_block()`, etc. //! //! # Quick Start //! //! ```ignore -//! use llm_worker::{Worker, Item}; +//! use llm_engine::{Engine, Item}; //! -//! // Create a Worker -//! let mut worker = Worker::new(client) +//! // Create a Engine +//! let mut engine = Engine::new(client) //! .system_prompt("You are a helpful assistant."); //! //! // Register tools (optional) -//! // worker.register_tool(my_tool_definition)?; +//! // engine.register_tool(my_tool_definition)?; //! //! // Run the interaction -//! let history = worker.run("Hello!").await?; +//! let history = engine.run("Hello!").await?; //! ``` //! //! # Cache Protection @@ -31,15 +31,15 @@ //! call `unlock_cache()` first; the next `run()` re-locks automatically. //! //! ```ignore -//! worker.run("user input").await?; -//! worker.unlock_cache(); -//! worker.set_system_prompt("new prompt"); -//! worker.run("next input").await?; +//! engine.run("user input").await?; +//! engine.unlock_cache(); +//! engine.set_system_prompt("new prompt"); +//! engine.run("next input").await?; //! ``` +mod engine; mod handler; mod message; -mod worker; pub(crate) mod callback; pub mod event; @@ -54,11 +54,12 @@ pub mod tool_server; pub mod usage_record; pub use callback::{TextBlockScope, ThinkingBlockScope, ToolUseBlockScope}; +pub use engine::{ + Engine, EngineConfig, EngineError, EngineResult, EngineRunOutput, LlmRetryNotice, + ToolRegistryError, +}; pub use handler::ToolUseBlockStart; pub use interceptor::Interceptor; pub use message::{ContentPart, Item, Message, Role}; pub use tool::{ToolCall, ToolExecutionContext, ToolOutputLimits, ToolResult}; pub use usage_record::UsageRecord; -pub use worker::{ - LlmRetryNotice, RunOutput, ToolRegistryError, Worker, WorkerConfig, WorkerError, WorkerResult, -}; diff --git a/crates/llm-worker/src/llm_client/auth.rs b/crates/llm-engine/src/llm_client/auth.rs similarity index 95% rename from crates/llm-worker/src/llm_client/auth.rs rename to crates/llm-engine/src/llm_client/auth.rs index a94b06a0..ba48fd6c 100644 --- a/crates/llm-worker/src/llm_client/auth.rs +++ b/crates/llm-engine/src/llm_client/auth.rs @@ -1,7 +1,7 @@ //! `Scheme` 実装と通信層が要求する認証要件、および動的認証プロバイダ。 //! //! マニフェスト側の型(`ModelConfig` / `SchemeKind` / `AuthRef`)は -//! `crates/manifest` に置き、llm-worker はそれを知らずに済む。 +//! `crates/manifest` に置き、llm-engine はそれを知らずに済む。 //! `AuthRequirement` は scheme が宣言する「この scheme はどんな認証を //! 期待するか」のランタイム記述で、manifest 側の `AuthRef` との //! 照合(`AuthRef → ResolvedAuth` 変換の適否)は `crates/provider` @@ -36,7 +36,7 @@ pub enum AuthRequirement { /// Codex OAuth のように access_token が refresh で更新されたり、 /// `ChatGPT-Account-Id` / `X-OpenAI-Fedramp` のような複数ヘッダを /// 同時に注入する必要があるケースで使う。実体は `crates/provider` -/// 側に置き、llm-worker は trait を知るだけ。 +/// 側に置き、llm-engine は trait を知るだけ。 /// /// 返したヘッダはそのまま `HeaderMap` に挿入される。`Authorization` /// 含む scheme 既定の認証ヘッダは送出されないので、必要なら diff --git a/crates/llm-worker/src/llm_client/capability.rs b/crates/llm-engine/src/llm_client/capability.rs similarity index 100% rename from crates/llm-worker/src/llm_client/capability.rs rename to crates/llm-engine/src/llm_client/capability.rs diff --git a/crates/llm-worker/src/llm_client/client.rs b/crates/llm-engine/src/llm_client/client.rs similarity index 98% rename from crates/llm-worker/src/llm_client/client.rs rename to crates/llm-engine/src/llm_client/client.rs index 43ddfdfd..d21acac8 100644 --- a/crates/llm-worker/src/llm_client/client.rs +++ b/crates/llm-engine/src/llm_client/client.rs @@ -81,7 +81,7 @@ impl Clone for Box { /// `Box` に対する `LlmClient` の実装 /// -/// これにより、動的ディスパッチを使用するクライアントも `Worker` で利用可能になる。 +/// これにより、動的ディスパッチを使用するクライアントも `Engine` で利用可能になる。 #[async_trait] impl LlmClient for Box { async fn stream(&self, request: Request) -> Result { diff --git a/crates/llm-worker/src/llm_client/error.rs b/crates/llm-engine/src/llm_client/error.rs similarity index 100% rename from crates/llm-worker/src/llm_client/error.rs rename to crates/llm-engine/src/llm_client/error.rs diff --git a/crates/llm-worker/src/llm_client/event.rs b/crates/llm-engine/src/llm_client/event.rs similarity index 100% rename from crates/llm-worker/src/llm_client/event.rs rename to crates/llm-engine/src/llm_client/event.rs diff --git a/crates/llm-worker/src/llm_client/mod.rs b/crates/llm-engine/src/llm_client/mod.rs similarity index 100% rename from crates/llm-worker/src/llm_client/mod.rs rename to crates/llm-engine/src/llm_client/mod.rs diff --git a/crates/llm-worker/src/llm_client/retry.rs b/crates/llm-engine/src/llm_client/retry.rs similarity index 95% rename from crates/llm-worker/src/llm_client/retry.rs rename to crates/llm-engine/src/llm_client/retry.rs index 1775cf98..77cb03a0 100644 --- a/crates/llm-worker/src/llm_client/retry.rs +++ b/crates/llm-engine/src/llm_client/retry.rs @@ -1,6 +1,6 @@ //! LLM response stream を開く前の transient error 向けリトライポリシー。 //! -//! Worker が `LlmClient::stream` の open error に対して `is_retryable` を見て +//! Engine が `LlmClient::stream` の open error に対して `is_retryable` を見て //! retry / backoff / TUI event / cancellation をまとめて管理する。 //! SSE 読み出し開始後の失敗は対象外。 @@ -8,8 +8,8 @@ use std::time::Duration; /// 指数バックオフ + ジッター + 累積タイムアウトを表すポリシー。 /// -/// `Default` は llm-worker 全体の固定値を返す。manifest 経由の上書きが -/// 必要になったら拡張する(現状は不要 → `tickets/llm-worker-transient-retry.md`)。 +/// `Default` は llm-engine 全体の固定値を返す。manifest 経由の上書きが +/// 必要になったら拡張する(現状は不要 → `tickets/llm-engine-transient-retry.md`)。 #[derive(Debug, Clone)] pub struct RetryPolicy { /// 指数の基準値。`base * 2^attempt` を `cap` で頭打ちにした上限から diff --git a/crates/llm-worker/src/llm_client/scheme/anthropic/capability.rs b/crates/llm-engine/src/llm_client/scheme/anthropic/capability.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/anthropic/capability.rs rename to crates/llm-engine/src/llm_client/scheme/anthropic/capability.rs diff --git a/crates/llm-worker/src/llm_client/scheme/anthropic/events.rs b/crates/llm-engine/src/llm_client/scheme/anthropic/events.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/anthropic/events.rs rename to crates/llm-engine/src/llm_client/scheme/anthropic/events.rs diff --git a/crates/llm-worker/src/llm_client/scheme/anthropic/mod.rs b/crates/llm-engine/src/llm_client/scheme/anthropic/mod.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/anthropic/mod.rs rename to crates/llm-engine/src/llm_client/scheme/anthropic/mod.rs diff --git a/crates/llm-worker/src/llm_client/scheme/anthropic/request.rs b/crates/llm-engine/src/llm_client/scheme/anthropic/request.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/anthropic/request.rs rename to crates/llm-engine/src/llm_client/scheme/anthropic/request.rs diff --git a/crates/llm-worker/src/llm_client/scheme/anthropic/scheme_impl.rs b/crates/llm-engine/src/llm_client/scheme/anthropic/scheme_impl.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/anthropic/scheme_impl.rs rename to crates/llm-engine/src/llm_client/scheme/anthropic/scheme_impl.rs diff --git a/crates/llm-worker/src/llm_client/scheme/gemini/capability.rs b/crates/llm-engine/src/llm_client/scheme/gemini/capability.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/gemini/capability.rs rename to crates/llm-engine/src/llm_client/scheme/gemini/capability.rs diff --git a/crates/llm-worker/src/llm_client/scheme/gemini/events.rs b/crates/llm-engine/src/llm_client/scheme/gemini/events.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/gemini/events.rs rename to crates/llm-engine/src/llm_client/scheme/gemini/events.rs diff --git a/crates/llm-worker/src/llm_client/scheme/gemini/mod.rs b/crates/llm-engine/src/llm_client/scheme/gemini/mod.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/gemini/mod.rs rename to crates/llm-engine/src/llm_client/scheme/gemini/mod.rs diff --git a/crates/llm-worker/src/llm_client/scheme/gemini/request.rs b/crates/llm-engine/src/llm_client/scheme/gemini/request.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/gemini/request.rs rename to crates/llm-engine/src/llm_client/scheme/gemini/request.rs diff --git a/crates/llm-worker/src/llm_client/scheme/gemini/scheme_impl.rs b/crates/llm-engine/src/llm_client/scheme/gemini/scheme_impl.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/gemini/scheme_impl.rs rename to crates/llm-engine/src/llm_client/scheme/gemini/scheme_impl.rs diff --git a/crates/llm-worker/src/llm_client/scheme/mod.rs b/crates/llm-engine/src/llm_client/scheme/mod.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/mod.rs rename to crates/llm-engine/src/llm_client/scheme/mod.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_chat/capability.rs b/crates/llm-engine/src/llm_client/scheme/openai_chat/capability.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_chat/capability.rs rename to crates/llm-engine/src/llm_client/scheme/openai_chat/capability.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_chat/events.rs b/crates/llm-engine/src/llm_client/scheme/openai_chat/events.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_chat/events.rs rename to crates/llm-engine/src/llm_client/scheme/openai_chat/events.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_chat/mod.rs b/crates/llm-engine/src/llm_client/scheme/openai_chat/mod.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_chat/mod.rs rename to crates/llm-engine/src/llm_client/scheme/openai_chat/mod.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_chat/request.rs b/crates/llm-engine/src/llm_client/scheme/openai_chat/request.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_chat/request.rs rename to crates/llm-engine/src/llm_client/scheme/openai_chat/request.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_chat/scheme_impl.rs b/crates/llm-engine/src/llm_client/scheme/openai_chat/scheme_impl.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_chat/scheme_impl.rs rename to crates/llm-engine/src/llm_client/scheme/openai_chat/scheme_impl.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_responses/capability.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/capability.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_responses/capability.rs rename to crates/llm-engine/src/llm_client/scheme/openai_responses/capability.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_responses/events.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/events.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_responses/events.rs rename to crates/llm-engine/src/llm_client/scheme/openai_responses/events.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_responses/mod.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/mod.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_responses/mod.rs rename to crates/llm-engine/src/llm_client/scheme/openai_responses/mod.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/request.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs rename to crates/llm-engine/src/llm_client/scheme/openai_responses/request.rs diff --git a/crates/llm-worker/src/llm_client/scheme/openai_responses/scheme_impl.rs b/crates/llm-engine/src/llm_client/scheme/openai_responses/scheme_impl.rs similarity index 100% rename from crates/llm-worker/src/llm_client/scheme/openai_responses/scheme_impl.rs rename to crates/llm-engine/src/llm_client/scheme/openai_responses/scheme_impl.rs diff --git a/crates/llm-worker/src/llm_client/transport.rs b/crates/llm-engine/src/llm_client/transport.rs similarity index 100% rename from crates/llm-worker/src/llm_client/transport.rs rename to crates/llm-engine/src/llm_client/transport.rs diff --git a/crates/llm-worker/src/llm_client/types.rs b/crates/llm-engine/src/llm_client/types.rs similarity index 99% rename from crates/llm-worker/src/llm_client/types.rs rename to crates/llm-engine/src/llm_client/types.rs index 14c6ac57..7a04d51f 100644 --- a/crates/llm-worker/src/llm_client/types.rs +++ b/crates/llm-engine/src/llm_client/types.rs @@ -62,7 +62,7 @@ impl fmt::Debug for RequestTrace { /// # Examples /// /// ```ignore -/// use llm_worker::Item; +/// use llm_engine::Item; /// /// let user = Item::user_message("Hello!"); /// let assistant = Item::assistant_message("Hi there!"); diff --git a/crates/llm-worker/src/message.rs b/crates/llm-engine/src/message.rs similarity index 100% rename from crates/llm-worker/src/message.rs rename to crates/llm-engine/src/message.rs diff --git a/crates/llm-worker/src/prune.rs b/crates/llm-engine/src/prune.rs similarity index 98% rename from crates/llm-worker/src/prune.rs rename to crates/llm-engine/src/prune.rs index 4b2307f2..c8da8ccf 100644 --- a/crates/llm-worker/src/prune.rs +++ b/crates/llm-engine/src/prune.rs @@ -9,7 +9,7 @@ //! Prune は **コンテキスト射影** であり、history の変換ではない。 //! この crate が提供するのは pure な候補抽出 [`prunable_indices`] のみで、 //! 射影の適用は上位層(`pod::prune_hook` 等)が LLM に送る一時コンテキスト -//! に対してだけ行う。Worker の永続履歴は決して変更されない。 +//! に対してだけ行う。Engine の永続履歴は決して変更されない。 //! //! 保護境界は末尾 token budget で決めるが、この crate は usage 履歴を //! 所有しない。prefix ごとの token 推定値と savings 推定は上位層から @@ -32,8 +32,8 @@ pub type TokenEstimator = Box Vec + Send + Syn /// Callback that estimates the token savings for projecting the /// `ToolResult.content` out of `history[i]` for each `i` in `indices`. /// -/// Injected into [`crate::Worker`] via `set_savings_estimator` so the -/// Worker can make `min_savings` decisions without knowing about usage +/// Injected into [`crate::Engine`] via `set_savings_estimator` so the +/// Engine can make `min_savings` decisions without knowing about usage /// measurement sources. Return `0` to signal "no data / refuse to prune". /// /// 推定対象は「drop する範囲全体」ではなく「content を None にする差分」 @@ -44,7 +44,7 @@ pub type SavingsEstimator = Box u64 + Send + Sync>; /// Result of one prune evaluation pass, surfaced to the optional /// [`PruneObserver`] for instrumentation. /// -/// Worker は LLM リクエストごとに 1 回 prune の評価をし、その結果を +/// Engine は LLM リクエストごとに 1 回 prune の評価をし、その結果を /// (observer が登録されていれば)この値で通知する。fire/skip の判定 /// 結果と、判定材料になった候補数 / 推定 savings / 保護領域の先頭 index を持つ。 #[derive(Debug, Clone)] @@ -61,7 +61,7 @@ pub struct PruneEvaluation { } /// Outcome of one prune evaluation. Each variant is one branch of the -/// "fire vs skip" decision tree the Worker walks before each LLM request. +/// "fire vs skip" decision tree the Engine walks before each LLM request. #[derive(Debug, Clone, PartialEq, Eq)] pub enum PruneDecision { /// `prunable_indices` が空 → 何もしない。 diff --git a/crates/llm-worker/src/state.rs b/crates/llm-engine/src/state.rs similarity index 67% rename from crates/llm-worker/src/state.rs rename to crates/llm-engine/src/state.rs index 2f67f0d6..836857fb 100644 --- a/crates/llm-worker/src/state.rs +++ b/crates/llm-engine/src/state.rs @@ -1,12 +1,12 @@ -//! Worker State +//! Engine State //! //! State marker types for cache protection using the Type-state pattern. -//! Worker has state transitions from `Mutable` → `Locked`. +//! Engine has state transitions from `Mutable` → `Locked`. -/// Marker trait representing Worker state +/// Marker trait representing Engine state /// /// This trait is sealed and cannot be implemented externally. -pub trait WorkerState: private::Sealed + Send + Sync + 'static {} +pub trait EngineState: private::Sealed + Send + Sync + 'static {} mod private { pub trait Sealed {} @@ -19,28 +19,28 @@ mod private { /// - Editing message history (add, delete, clear) /// - Registering tools and hooks /// -/// Can transition to [`Locked`] state via `Worker::lock()`. +/// Can transition to [`Locked`] state via `Engine::lock()`. /// /// # Examples /// /// ```ignore -/// use llm_worker::Worker; +/// use llm_engine::Engine; /// -/// let mut worker = Worker::new(client) +/// let mut engine = Engine::new(client) /// .system_prompt("You are helpful."); /// /// // History can be edited -/// worker.push_message(Message::user("Hello")); -/// worker.clear_history(); +/// engine.push_message(Message::user("Hello")); +/// engine.clear_history(); /// /// // Lock to protected state -/// let locked = worker.lock(); +/// let locked = engine.lock(); /// ``` #[derive(Debug, Clone, Copy, Default)] pub struct Mutable; impl private::Sealed for Mutable {} -impl WorkerState for Mutable {} +impl EngineState for Mutable {} /// Cache locked state (cache protected) /// @@ -51,10 +51,10 @@ impl WorkerState for Mutable {} /// To ensure LLM API KV cache hits, /// using this state during execution is recommended. /// -/// Can return to [`Mutable`] state via `Worker::unlock()`, +/// Can return to [`Mutable`] state via `Engine::unlock()`, /// but note that cache protection will be released. #[derive(Debug, Clone, Copy, Default)] pub struct Locked; impl private::Sealed for Locked {} -impl WorkerState for Locked {} +impl EngineState for Locked {} diff --git a/crates/llm-worker/src/timeline/event.rs b/crates/llm-engine/src/timeline/event.rs similarity index 100% rename from crates/llm-worker/src/timeline/event.rs rename to crates/llm-engine/src/timeline/event.rs diff --git a/crates/llm-worker/src/timeline/mod.rs b/crates/llm-engine/src/timeline/mod.rs similarity index 100% rename from crates/llm-worker/src/timeline/mod.rs rename to crates/llm-engine/src/timeline/mod.rs diff --git a/crates/llm-worker/src/timeline/text_block_collector.rs b/crates/llm-engine/src/timeline/text_block_collector.rs similarity index 100% rename from crates/llm-worker/src/timeline/text_block_collector.rs rename to crates/llm-engine/src/timeline/text_block_collector.rs diff --git a/crates/llm-worker/src/timeline/thinking_block_collector.rs b/crates/llm-engine/src/timeline/thinking_block_collector.rs similarity index 100% rename from crates/llm-worker/src/timeline/thinking_block_collector.rs rename to crates/llm-engine/src/timeline/thinking_block_collector.rs diff --git a/crates/llm-worker/src/timeline/timeline.rs b/crates/llm-engine/src/timeline/timeline.rs similarity index 99% rename from crates/llm-worker/src/timeline/timeline.rs rename to crates/llm-engine/src/timeline/timeline.rs index b28259ff..e7970ded 100644 --- a/crates/llm-worker/src/timeline/timeline.rs +++ b/crates/llm-engine/src/timeline/timeline.rs @@ -1,7 +1,7 @@ //! Timeline層 //! //! LLMからのイベントストリームを受信し、登録されたHandlerにディスパッチします。 -//! 通常はWorker経由で使用しますが、直接使用することも可能です。 +//! 通常はEngine経由で使用しますが、直接使用することも可能です。 use std::{collections::HashMap, marker::PhantomData}; @@ -348,7 +348,7 @@ where /// # Examples /// /// ```ignore -/// use llm_worker::{Timeline, Handler, TextBlockKind, TextBlockEvent}; +/// use llm_engine::{Timeline, Handler, TextBlockKind, TextBlockEvent}; /// /// struct MyHandler; /// impl Handler for MyHandler { diff --git a/crates/llm-worker/src/timeline/tool_call_collector.rs b/crates/llm-engine/src/timeline/tool_call_collector.rs similarity index 100% rename from crates/llm-worker/src/timeline/tool_call_collector.rs rename to crates/llm-engine/src/timeline/tool_call_collector.rs diff --git a/crates/llm-worker/src/token_counter.rs b/crates/llm-engine/src/token_counter.rs similarity index 100% rename from crates/llm-worker/src/token_counter.rs rename to crates/llm-engine/src/token_counter.rs diff --git a/crates/llm-worker/src/tool.rs b/crates/llm-engine/src/tool.rs similarity index 95% rename from crates/llm-worker/src/tool.rs rename to crates/llm-engine/src/tool.rs index e90ffb12..fdb2a388 100644 --- a/crates/llm-worker/src/tool.rs +++ b/crates/llm-engine/src/tool.rs @@ -33,7 +33,7 @@ pub enum ToolError { /// Outputs this small don't benefit from pruning. pub const SUMMARY_THRESHOLD: usize = 200; -/// Byte-size caps applied to tool execution `content` at the Worker's +/// Byte-size caps applied to tool execution `content` at the Engine's /// tool-execution boundary, before results enter conversation history. /// /// Exists so a single oversized tool result (e.g. a wide `Glob` scan) @@ -131,7 +131,7 @@ impl From for ToolOutput { /// /// This metadata is intentionally not part of the provider-facing tool schema. /// It lets host layers audit where a model-visible tool definition came from -/// while keeping execution and permission semantics in the normal Worker path. +/// while keeping execution and permission semantics in the normal Engine path. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ToolOrigin { /// Origin kind, for example `plugin` or `builtin`. @@ -154,7 +154,7 @@ pub struct ToolOrigin { /// Tool meta information (fixed at registration, immutable) /// -/// Generated from `ToolDefinition` factory and does not change after registration with Worker. +/// Generated from `ToolDefinition` factory and does not change after registration with Engine. /// Used for sending tool definitions to LLM. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ToolMeta { @@ -205,7 +205,7 @@ impl ToolMeta { /// Tool definition factory /// /// When called, returns `(ToolMeta, Arc)`. -/// Called once during Worker registration, and the meta information and instance +/// Called once during Engine registration, and the meta information and instance /// are cached at session scope. /// /// # Examples @@ -219,22 +219,22 @@ impl ToolMeta { /// Arc::new(MyToolImpl { state: 0 }) as Arc, /// ) /// }); -/// worker.register_tool(def)?; +/// engine.register_tool(def)?; /// ``` pub type ToolDefinition = Arc (ToolMeta, Arc) + Send + Sync>; -/// Per-call context supplied by the worker when executing a tool call. +/// Per-call context supplied by the engine when executing a tool call. /// /// The context identifies a tool call within one assistant response's tool-call -/// batch without imposing any scheduling policy on the worker. Tool +/// batch without imposing any scheduling policy on the engine. Tool /// implementations may use it for response-local ordering, diagnostics, or -/// correlation, but it is intentionally not a handle to worker state, history, +/// correlation, but it is intentionally not a handle to engine state, history, /// or session mutation. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ToolExecutionContext { /// Provider/tool-call id for the call being executed. pub call_id: String, - /// Worker-local identity shared by all tool calls from one execution batch. + /// Engine-local identity shared by all tool calls from one execution batch. pub batch_id: String, /// Zero-based order of this call in the model-returned tool-call list. pub call_index: usize, @@ -249,7 +249,7 @@ impl ToolExecutionContext { } } - /// Context for direct, non-worker calls in unit tests and low-level callers. + /// Context for direct, non-engine calls in unit tests and low-level callers. pub fn direct() -> Self { Self::new("direct", "direct", 0) } @@ -285,13 +285,13 @@ impl Default for ToolExecutionContext { /// } /// /// // Register -/// worker.register_tool(app.search_definition())?; +/// engine.register_tool(app.search_definition())?; /// ``` /// /// # Manual Implementation /// /// ```ignore -/// use llm_worker::tool::{Tool, ToolError, ToolExecutionContext, ToolMeta, ToolDefinition, ToolOutput}; +/// use llm_engine::tool::{Tool, ToolError, ToolExecutionContext, ToolMeta, ToolDefinition, ToolOutput}; /// use std::sync::Arc; /// /// struct MyTool { counter: std::sync::atomic::AtomicUsize } diff --git a/crates/llm-worker/src/tool_server.rs b/crates/llm-engine/src/tool_server.rs similarity index 97% rename from crates/llm-worker/src/tool_server.rs rename to crates/llm-engine/src/tool_server.rs index fb884df4..6847dc9b 100644 --- a/crates/llm-worker/src/tool_server.rs +++ b/crates/llm-engine/src/tool_server.rs @@ -5,7 +5,7 @@ use thiserror::Error; use crate::llm_client::ToolDefinition as LlmToolDefinition; use crate::tool::{ - Tool, ToolDefinition as WorkerToolDefinition, ToolExecutionContext, ToolMeta, ToolOutput, + Tool, ToolDefinition as EngineToolDefinition, ToolExecutionContext, ToolMeta, ToolOutput, }; type ToolMap = HashMap)>; @@ -28,7 +28,7 @@ pub enum ToolServerError { #[derive(Clone, Default)] pub struct ToolServer { tools: Arc>, - pending: Arc>>, + pending: Arc>>, } impl ToolServer { @@ -50,7 +50,7 @@ impl ToolServer { #[derive(Clone, Default)] pub struct ToolServerHandle { tools: Arc>, - pending: Arc>>, + pending: Arc>>, } impl ToolServerHandle { @@ -58,8 +58,8 @@ impl ToolServerHandle { /// /// The factory is **not** called here; it is stored and executed /// when [`flush_pending`](Self::flush_pending) is called (typically - /// at the start of `Worker::run()`). - pub(crate) fn register_tool(&self, factory: WorkerToolDefinition) { + /// at the start of `Engine::run()`). + pub(crate) fn register_tool(&self, factory: EngineToolDefinition) { self.pending .lock() .unwrap_or_else(|e| e.into_inner()) @@ -67,14 +67,14 @@ impl ToolServerHandle { } /// Queue many tool factories for deferred initialization. - pub(crate) fn register_tools(&self, factories: impl IntoIterator) { + pub(crate) fn register_tools(&self, factories: impl IntoIterator) { let mut guard = self.pending.lock().unwrap_or_else(|e| e.into_inner()); guard.extend(factories); } /// Execute all pending factories and register the resulting tools. /// - /// Called implicitly by `Worker::lock()` before the first turn. + /// Called implicitly by `Engine::lock()` before the first turn. /// Exposed as `pub` so higher layers (e.g. Pod) can force-materialise /// tools earlier — for example when building a system-prompt template /// context that needs the list of registered tool names. Redundant @@ -150,7 +150,7 @@ impl ToolServerHandle { /// The factory is called immediately and the resulting tool overwrites /// the entry with the same name. Returns `ToolNotFound` if the name /// produced by the factory does not match any registered tool. - pub fn replace(&self, factory: WorkerToolDefinition) -> Result<(), ToolServerError> { + pub fn replace(&self, factory: EngineToolDefinition) -> Result<(), ToolServerError> { let (meta, instance) = factory(); let mut guard = self.tools.lock().unwrap_or_else(|e| e.into_inner()); if !guard.contains_key(&meta.name) { diff --git a/crates/llm-worker/src/usage_record.rs b/crates/llm-engine/src/usage_record.rs similarity index 100% rename from crates/llm-worker/src/usage_record.rs rename to crates/llm-engine/src/usage_record.rs diff --git a/crates/llm-worker/tests/anthropic_fixtures.rs b/crates/llm-engine/tests/anthropic_fixtures.rs similarity index 100% rename from crates/llm-worker/tests/anthropic_fixtures.rs rename to crates/llm-engine/tests/anthropic_fixtures.rs diff --git a/crates/llm-worker/tests/callback_test.rs b/crates/llm-engine/tests/callback_test.rs similarity index 84% rename from crates/llm-worker/tests/callback_test.rs rename to crates/llm-engine/tests/callback_test.rs index 20aa3bb8..35852906 100644 --- a/crates/llm-worker/tests/callback_test.rs +++ b/crates/llm-engine/tests/callback_test.rs @@ -1,6 +1,6 @@ //! Closure callback API tests //! -//! Tests for the closure-based event subscription API on Worker. +//! Tests for the closure-based event subscription API on Engine. mod common; @@ -10,11 +10,11 @@ use std::time::Duration; use async_trait::async_trait; use common::MockLlmClient; -use llm_worker::Worker; -use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent as ClientStatusEvent}; -use llm_worker::llm_client::retry::RetryPolicy; -use llm_worker::llm_client::{ClientError, LlmClient, Request, ResponseStream}; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::Engine; +use llm_engine::llm_client::event::{Event, ResponseStatus, StatusEvent as ClientStatusEvent}; +use llm_engine::llm_client::retry::RetryPolicy; +use llm_engine::llm_client::{ClientError, LlmClient, Request, ResponseStream}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; #[derive(Clone)] struct FailOnceClient { @@ -52,7 +52,7 @@ async fn test_callback_llm_retry_event() { calls: Arc::new(AtomicUsize::new(0)), events, }; - let mut worker = Worker::new(client).with_retry_policy(RetryPolicy { + let mut engine = Engine::new(client).with_retry_policy(RetryPolicy { base: Duration::from_millis(1), cap: Duration::from_millis(1), max_attempts: 2, @@ -61,12 +61,12 @@ async fn test_callback_llm_retry_event() { let notices = Arc::new(Mutex::new(Vec::new())); let sink = notices.clone(); - worker.on_llm_retry(move |llm_call, notice| { + engine.on_llm_retry(move |llm_call, notice| { sink.lock().unwrap().push((llm_call, notice.clone())); }); - let result = worker.run("retry once").await; - assert!(result.is_ok(), "worker should succeed after one retry"); + let result = engine.run("retry once").await; + assert!(result.is_ok(), "engine should succeed after one retry"); let notices = notices.lock().unwrap(); assert_eq!(notices.len(), 1); @@ -90,14 +90,14 @@ async fn test_callback_text_block_events() { ]; let client = MockLlmClient::new(events); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let text_deltas = Arc::new(Mutex::new(Vec::new())); let text_completes = Arc::new(Mutex::new(Vec::new())); let deltas = text_deltas.clone(); let completes = text_completes.clone(); - worker.on_text_block(move |block| { + engine.on_text_block(move |block| { let d = deltas.clone(); block.on_delta(move |text| { d.lock().unwrap().push(text.to_owned()); @@ -108,9 +108,9 @@ async fn test_callback_text_block_events() { }); }); - // Mutable::run consumes self, returns (Locked, WorkerResult) - let result = worker.run("Greet me").await; - assert!(result.is_ok(), "Worker should complete"); + // Mutable::run consumes self, returns (Locked, EngineResult) + let result = engine.run("Greet me").await; + assert!(result.is_ok(), "Engine should complete"); let deltas = text_deltas.lock().unwrap(); assert_eq!(deltas.len(), 2); @@ -136,14 +136,14 @@ async fn test_callback_tool_call_complete() { ]; let client = MockLlmClient::new(events); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let tool_starts = Arc::new(Mutex::new(Vec::<(String, String)>::new())); let tool_completes = Arc::new(Mutex::new(Vec::new())); let starts = tool_starts.clone(); let completes = tool_completes.clone(); - worker.on_tool_use_block(move |start, block| { + engine.on_tool_use_block(move |start, block| { starts .lock() .unwrap() @@ -154,8 +154,8 @@ async fn test_callback_tool_call_complete() { }); }); - // Mutable::run consumes self, returns (Locked, WorkerResult) - let _ = worker.run("Weather please").await; + // Mutable::run consumes self, returns (Locked, EngineResult) + let _ = engine.run("Weather please").await; let starts = tool_starts.lock().unwrap(); assert_eq!(starts.len(), 1); @@ -182,23 +182,23 @@ async fn test_callback_turn_events() { ]; let client = MockLlmClient::new(events); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let turn_starts = Arc::new(Mutex::new(Vec::new())); let turn_ends = Arc::new(Mutex::new(Vec::new())); let starts = turn_starts.clone(); - worker.on_turn_start(move |turn| { + engine.on_turn_start(move |turn| { starts.lock().unwrap().push(turn); }); let ends = turn_ends.clone(); - worker.on_turn_end(move |turn| { + engine.on_turn_end(move |turn| { ends.lock().unwrap().push(turn); }); - // Mutable::run consumes self, returns (Locked, WorkerResult) - let result = worker.run("Do something").await; + // Mutable::run consumes self, returns (Locked, EngineResult) + let result = engine.run("Do something").await; assert!(result.is_ok()); let starts = turn_starts.lock().unwrap(); @@ -221,7 +221,7 @@ impl Tool for FixedOutputTool { async fn execute( &self, _input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { Ok(self.output.clone()) } @@ -253,9 +253,9 @@ async fn test_callback_tool_result_events() { ]; let client = MockLlmClient::new(events); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); - worker.register_tool(fixed_tool( + engine.register_tool(fixed_tool( "fixed", ToolOutput { summary: "did the thing".into(), @@ -266,7 +266,7 @@ async fn test_callback_tool_result_events() { let captured: Arc, bool)>>> = Arc::new(Mutex::new(Vec::new())); let sink = captured.clone(); - worker.on_tool_result(move |result| { + engine.on_tool_result(move |result| { sink.lock().unwrap().push(( result.tool_use_id.clone(), result.summary.clone(), @@ -275,7 +275,7 @@ async fn test_callback_tool_result_events() { )); }); - let _ = worker.run("call it").await; + let _ = engine.run("call it").await; let observed = captured.lock().unwrap(); assert_eq!(observed.len(), 1); @@ -296,7 +296,7 @@ impl Tool for ErroringTool { async fn execute( &self, _input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { Err(ToolError::ExecutionFailed(self.message.clone())) } @@ -328,14 +328,14 @@ async fn test_callback_tool_result_error_path() { ]; let client = MockLlmClient::new(events); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); - worker.register_tool(erroring_tool("erroring", "boom")); + engine.register_tool(erroring_tool("erroring", "boom")); let captured: Arc, bool)>>> = Arc::new(Mutex::new(Vec::new())); let sink = captured.clone(); - worker.on_tool_result(move |result| { + engine.on_tool_result(move |result| { sink.lock().unwrap().push(( result.tool_use_id.clone(), result.summary.clone(), @@ -344,7 +344,7 @@ async fn test_callback_tool_result_error_path() { )); }); - let _ = worker.run("fail it").await; + let _ = engine.run("fail it").await; let observed = captured.lock().unwrap(); assert_eq!(observed.len(), 1); @@ -372,17 +372,17 @@ async fn test_callback_usage_events() { ]; let client = MockLlmClient::new(events); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let usage_events = Arc::new(Mutex::new(Vec::new())); let usages = usage_events.clone(); - worker.on_usage(move |event| { + engine.on_usage(move |event| { usages.lock().unwrap().push(event.clone()); }); - // Mutable::run consumes self, returns (Locked, WorkerResult) - let _ = worker.run("Hello").await; + // Mutable::run consumes self, returns (Locked, EngineResult) + let _ = engine.run("Hello").await; let usages = usage_events.lock().unwrap(); assert_eq!(usages.len(), 1); diff --git a/crates/llm-worker/tests/common/mod.rs b/crates/llm-engine/tests/common/mod.rs similarity index 97% rename from crates/llm-worker/tests/common/mod.rs rename to crates/llm-engine/tests/common/mod.rs index e06fc088..2c52d200 100644 --- a/crates/llm-worker/tests/common/mod.rs +++ b/crates/llm-engine/tests/common/mod.rs @@ -8,9 +8,9 @@ use std::sync::{Arc, Mutex}; use async_trait::async_trait; use futures::Stream; -use llm_worker::llm_client::event::{BlockType, DeltaContent, Event}; -use llm_worker::llm_client::{ClientError, LlmClient, Request}; -use llm_worker::timeline::{Handler, TextBlockEvent, TextBlockKind, Timeline}; +use llm_engine::llm_client::event::{BlockType, DeltaContent, Event}; +use llm_engine::llm_client::{ClientError, LlmClient, Request}; +use llm_engine::timeline::{Handler, TextBlockEvent, TextBlockKind, Timeline}; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -272,7 +272,7 @@ pub fn assert_timeline_integration(subdir: &str) { }); for event in &events { - let timeline_event: llm_worker::timeline::event::Event = event.clone().into(); + let timeline_event: llm_engine::timeline::event::Event = event.clone().into(); timeline.dispatch(&timeline_event); } diff --git a/crates/llm-worker/tests/compile_fail.rs b/crates/llm-engine/tests/compile_fail.rs similarity index 100% rename from crates/llm-worker/tests/compile_fail.rs rename to crates/llm-engine/tests/compile_fail.rs diff --git a/crates/llm-worker/tests/worker_fixtures.rs b/crates/llm-engine/tests/engine_fixtures.rs similarity index 81% rename from crates/llm-worker/tests/worker_fixtures.rs rename to crates/llm-engine/tests/engine_fixtures.rs index 8023e20b..c951ca62 100644 --- a/crates/llm-worker/tests/worker_fixtures.rs +++ b/crates/llm-engine/tests/engine_fixtures.rs @@ -1,6 +1,6 @@ -//! Worker fixture-based integration tests +//! Engine fixture-based integration tests //! -//! Tests Worker behavior using recorded API responses. +//! Tests Engine behavior using recorded API responses. //! Can run locally without API keys. mod common; @@ -11,8 +11,8 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use async_trait::async_trait; use common::MockLlmClient; -use llm_worker::Worker; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::Engine; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; /// Fixture directory path fn fixtures_dir() -> std::path::PathBuf { @@ -61,7 +61,7 @@ impl Tool for MockWeatherTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { self.call_count.fetch_add(1, Ordering::SeqCst); @@ -102,7 +102,7 @@ fn test_mock_client_from_fixture() { /// Creates a client with programmatically constructed events instead of using fixture files. #[test] fn test_mock_client_from_events() { - use llm_worker::llm_client::event::Event; + use llm_engine::llm_client::event::Event; // Specify events directly let events = vec![ @@ -116,54 +116,54 @@ fn test_mock_client_from_events() { } // ============================================================================= -// Worker Tests with Fixtures +// Engine Tests with Fixtures // ============================================================================= -/// Verify that Worker can correctly process simple text responses +/// Verify that Engine can correctly process simple text responses /// /// Uses simple_text.jsonl fixture to test scenarios without tool calls. /// Skipped if fixture is not present. #[tokio::test] -async fn test_worker_simple_text_response() { +async fn test_engine_simple_text_response() { let fixture_path = fixtures_dir().join("simple_text.jsonl"); if !fixture_path.exists() { println!("Fixture not found: {:?}, skipping test", fixture_path); - println!("Run: cargo run --example record_worker_test"); + println!("Run: cargo run --example record_engine_test"); return; } let client = MockLlmClient::from_fixture(&fixture_path).unwrap(); - let worker = Worker::new(client); + let engine = Engine::new(client); // Send a simple message (Mutable::run consumes self, returns tuple) - let result = worker.run("Hello").await; + let result = engine.run("Hello").await; - assert!(result.is_ok(), "Worker should complete successfully"); + assert!(result.is_ok(), "Engine should complete successfully"); } -/// Verify that Worker can correctly process responses containing tool calls +/// Verify that Engine can correctly process responses containing tool calls /// /// Uses tool_call.jsonl fixture to test that MockWeatherTool is called. /// Sets max_turns=1 to prevent loop after tool execution. #[tokio::test] -async fn test_worker_tool_call() { +async fn test_engine_tool_call() { let fixture_path = fixtures_dir().join("tool_call.jsonl"); if !fixture_path.exists() { println!("Fixture not found: {:?}, skipping test", fixture_path); - println!("Run: cargo run --example record_worker_test"); + println!("Run: cargo run --example record_engine_test"); return; } let client = MockLlmClient::from_fixture(&fixture_path).unwrap(); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); // Register tool let weather_tool = MockWeatherTool::new(); let tool_for_check = weather_tool.clone(); - worker.register_tool(weather_tool.definition()); + engine.register_tool(weather_tool.definition()); // Send message (Mutable::run consumes self, returns tuple) - let _result = worker.run("What's the weather in Tokyo?").await; + let _result = engine.run("What's the weather in Tokyo?").await; // Verify tool was called // Note: max_turns=1 so no request is sent after tool result @@ -174,13 +174,13 @@ async fn test_worker_tool_call() { // But ends after 1 turn due to max_turns=1 } -/// Verify that Worker works without fixture files +/// Verify that Engine works without fixture files /// /// Constructs event sequence programmatically and passes to MockLlmClient. /// Useful when test independence is needed and external file dependency should be eliminated. #[tokio::test] -async fn test_worker_with_programmatic_events() { - use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent}; +async fn test_engine_with_programmatic_events() { + use llm_engine::llm_client::event::{Event, ResponseStatus, StatusEvent}; // Construct event sequence programmatically let events = vec![ @@ -194,12 +194,12 @@ async fn test_worker_with_programmatic_events() { ]; let client = MockLlmClient::new(events); - let worker = Worker::new(client); + let engine = Engine::new(client); // Mutable::run consumes self, returns tuple - let result = worker.run("Greet me").await; + let result = engine.run("Greet me").await; - assert!(result.is_ok(), "Worker should complete successfully"); + assert!(result.is_ok(), "Engine should complete successfully"); } /// Verify that ToolCallCollector correctly collects ToolCall from ToolUse block events @@ -208,8 +208,8 @@ async fn test_worker_with_programmatic_events() { /// correctly extracts id, name, and input (JSON). #[tokio::test] async fn test_tool_call_collector_integration() { - use llm_worker::llm_client::event::Event; - use llm_worker::timeline::{Timeline, ToolCallCollector}; + use llm_engine::llm_client::event::Event; + use llm_engine::timeline::{Timeline, ToolCallCollector}; // Event sequence containing ToolUse block let events = vec![ @@ -225,7 +225,7 @@ async fn test_tool_call_collector_integration() { // Dispatch events for event in &events { - let timeline_event: llm_worker::timeline::event::Event = event.clone().into(); + let timeline_event: llm_engine::timeline::event::Event = event.clone().into(); timeline.dispatch(&timeline_event); } diff --git a/crates/llm-worker/tests/worker_state_test.rs b/crates/llm-engine/tests/engine_state_test.rs similarity index 72% rename from crates/llm-worker/tests/worker_state_test.rs rename to crates/llm-engine/tests/engine_state_test.rs index 58c7cf33..12faac64 100644 --- a/crates/llm-worker/tests/worker_state_test.rs +++ b/crates/llm-engine/tests/engine_state_test.rs @@ -1,4 +1,4 @@ -//! Worker state management tests +//! Engine state management tests //! //! Tests for state transitions using the Type-state pattern (Mutable/Locked) //! and state preservation between turns. @@ -10,10 +10,10 @@ use std::sync::{Arc, Mutex}; use async_trait::async_trait; use common::MockLlmClient; -use llm_worker::Item; -use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent}; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; -use llm_worker::{Worker, WorkerError}; +use llm_engine::Item; +use llm_engine::llm_client::event::{Event, ResponseStatus, StatusEvent}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::{Engine, EngineError}; // ============================================================================= // Mutable State Tests @@ -23,13 +23,13 @@ use llm_worker::{Worker, WorkerError}; #[test] fn test_mutable_set_system_prompt() { let client = MockLlmClient::new(vec![]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); - assert!(worker.get_system_prompt().is_none()); + assert!(engine.get_system_prompt().is_none()); - worker.set_system_prompt("You are a helpful assistant."); + engine.set_system_prompt("You are a helpful assistant."); assert_eq!( - worker.get_system_prompt(), + engine.get_system_prompt(), Some("You are a helpful assistant.") ); } @@ -38,41 +38,41 @@ fn test_mutable_set_system_prompt() { #[test] fn test_mutable_history_manipulation() { let client = MockLlmClient::new(vec![]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); // Initial state is empty - assert!(worker.history().is_empty()); + assert!(engine.history().is_empty()); // Add to history - worker.append_history(vec![Item::user_message("Hello")]); - worker.append_history(vec![Item::assistant_message("Hi there!")]); - assert_eq!(worker.history().len(), 2); + engine.append_history(vec![Item::user_message("Hello")]); + engine.append_history(vec![Item::assistant_message("Hi there!")]); + assert_eq!(engine.history().len(), 2); // Append to history via the callback-aware API. - worker.append_history(vec![Item::user_message("How are you?")]); - assert_eq!(worker.history().len(), 3); + engine.append_history(vec![Item::user_message("How are you?")]); + assert_eq!(engine.history().len(), 3); // Clear history - worker.clear_history(); - assert!(worker.history().is_empty()); + engine.clear_history(); + assert!(engine.history().is_empty()); // Set history let items = vec![ Item::user_message("Test"), Item::assistant_message("Response"), ]; - worker.set_history(items); - assert_eq!(worker.history().len(), 2); + engine.set_history(items); + assert_eq!(engine.history().len(), 2); } -/// Verify that Worker can be constructed using builder pattern +/// Verify that Engine can be constructed using builder pattern #[test] fn test_mutable_builder_pattern() { let client = MockLlmClient::new(vec![]); - let worker = Worker::new(client).system_prompt("System prompt"); + let engine = Engine::new(client).system_prompt("System prompt"); - assert_eq!(worker.get_system_prompt(), Some("System prompt")); - assert!(worker.history().is_empty()); + assert_eq!(engine.get_system_prompt(), Some("System prompt")); + assert!(engine.history().is_empty()); } /// Verify that multiple items can be added with append_history and callbacks fire. @@ -81,22 +81,22 @@ fn test_mutable_append_history() { let client = MockLlmClient::new(vec![]); let observed = Arc::new(Mutex::new(Vec::new())); let observed_for_callback = Arc::clone(&observed); - let mut worker = Worker::new(client); - worker.on_history_append(move |item| { + let mut engine = Engine::new(client); + engine.on_history_append(move |item| { if let Some(text) = item.as_text() { observed_for_callback.lock().unwrap().push(text.to_string()); } }); - worker.append_history(vec![Item::user_message("First")]); + engine.append_history(vec![Item::user_message("First")]); - worker.append_history(vec![ + engine.append_history(vec![ Item::assistant_message("Response 1"), Item::user_message("Second"), Item::assistant_message("Response 2"), ]); - assert_eq!(worker.history().len(), 4); + assert_eq!(engine.history().len(), 4); assert_eq!( observed.lock().unwrap().as_slice(), ["First", "Response 1", "Second", "Response 2"] @@ -139,7 +139,7 @@ impl Tool for CountingTool { async fn execute( &self, _input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { self.calls.fetch_add(1, Ordering::SeqCst); Ok(format!("{}-ok", self.name).into()) @@ -150,11 +150,11 @@ impl Tool for CountingTool { #[test] fn test_mutable_can_register_tool() { let client = MockLlmClient::new(vec![]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let tool = CountingTool::new("count_tool"); // register_tool is infallible (factory deferred to run-time flush) - worker.register_tool(tool.definition()); + engine.register_tool(tool.definition()); } // ============================================================================= @@ -165,37 +165,37 @@ fn test_mutable_can_register_tool() { #[test] fn test_lock_transition() { let client = MockLlmClient::new(vec![]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); - worker.set_system_prompt("System"); - worker.append_history(vec![Item::user_message("Hello")]); - worker.append_history(vec![Item::assistant_message("Hi")]); + engine.set_system_prompt("System"); + engine.append_history(vec![Item::user_message("Hello")]); + engine.append_history(vec![Item::assistant_message("Hi")]); // Lock - let locked_worker = worker.lock(); + let locked_engine = engine.lock(); // History and system prompt are still accessible in Locked state - assert_eq!(locked_worker.get_system_prompt(), Some("System")); - assert_eq!(locked_worker.history().len(), 2); - assert_eq!(locked_worker.locked_prefix_len(), 2); + assert_eq!(locked_engine.get_system_prompt(), Some("System")); + assert_eq!(locked_engine.history().len(), 2); + assert_eq!(locked_engine.locked_prefix_len(), 2); } /// Verify that unlock() transitions from Locked -> Mutable state #[test] fn test_unlock_transition() { let client = MockLlmClient::new(vec![]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); - worker.append_history(vec![Item::user_message("Hello")]); - let locked_worker = worker.lock(); + engine.append_history(vec![Item::user_message("Hello")]); + let locked_engine = engine.lock(); // Unlock - let mut worker = locked_worker.unlock(); + let mut engine = locked_engine.unlock(); // History operations are available again in Mutable state - worker.append_history(vec![Item::assistant_message("Hi")]); - worker.clear_history(); - assert!(worker.history().is_empty()); + engine.append_history(vec![Item::assistant_message("Hi")]); + engine.clear_history(); + assert!(engine.history().is_empty()); } // ============================================================================= @@ -204,7 +204,7 @@ fn test_unlock_transition() { /// Verify that history is correctly updated after running a turn in Mutable state #[tokio::test] -async fn test_mutable_run_updates_history() -> Result<(), WorkerError> { +async fn test_mutable_run_updates_history() -> Result<(), EngineError> { let events = vec![ Event::text_block_start(0), Event::text_delta(0, "Hello, I'm an assistant!"), @@ -215,14 +215,14 @@ async fn test_mutable_run_updates_history() -> Result<(), WorkerError> { ]; let client = MockLlmClient::new(events); - let worker = Worker::new(client); + let engine = Engine::new(client); - // Execute (Mutable::run consumes self, returns RunOutput) - let out = worker.run("Hi there").await?; - let worker = out.worker; + // Execute (Mutable::run consumes self, returns EngineRunOutput) + let out = engine.run("Hi there").await?; + let engine = out.engine; // History is updated - let history = worker.history(); + let history = engine.history(); assert_eq!(history.len(), 2); // user + assistant // User message @@ -259,24 +259,24 @@ async fn test_locked_multi_turn_history_accumulation() { ], ]); - let worker = Worker::new(client).system_prompt("You are helpful."); + let engine = Engine::new(client).system_prompt("You are helpful."); // Lock (after setting system prompt) - let mut locked_worker = worker.lock(); - assert_eq!(locked_worker.locked_prefix_len(), 0); // No items yet + let mut locked_engine = engine.lock(); + assert_eq!(locked_engine.locked_prefix_len(), 0); // No items yet // Turn 1 - let result1 = locked_worker.run("Hello!").await; + let result1 = locked_engine.run("Hello!").await; assert!(result1.is_ok()); - assert_eq!(locked_worker.history().len(), 2); // user + assistant + assert_eq!(locked_engine.history().len(), 2); // user + assistant // Turn 2 - let result2 = locked_worker.run("Can you help me?").await; + let result2 = locked_engine.run("Can you help me?").await; assert!(result2.is_ok()); - assert_eq!(locked_worker.history().len(), 4); // 2 * (user + assistant) + assert_eq!(locked_engine.history().len(), 4); // 2 * (user + assistant) // Verify history contents - let history = locked_worker.history(); + let history = locked_engine.history(); // Turn 1 user message assert_eq!(history[0].as_text(), Some("Hello!")); @@ -313,29 +313,29 @@ async fn test_locked_prefix_len_tracking() { ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); // Add items beforehand - worker.append_history(vec![Item::user_message("Pre-existing message 1")]); - worker.append_history(vec![Item::assistant_message("Pre-existing response 1")]); + engine.append_history(vec![Item::user_message("Pre-existing message 1")]); + engine.append_history(vec![Item::assistant_message("Pre-existing response 1")]); - assert_eq!(worker.history().len(), 2); + assert_eq!(engine.history().len(), 2); // Lock - let mut locked_worker = worker.lock(); - assert_eq!(locked_worker.locked_prefix_len(), 2); // 2 items at lock time + let mut locked_engine = engine.lock(); + assert_eq!(locked_engine.locked_prefix_len(), 2); // 2 items at lock time // Execute turn - locked_worker.run("New message").await.unwrap(); + locked_engine.run("New message").await.unwrap(); // History grows but locked_prefix_len remains unchanged - assert_eq!(locked_worker.history().len(), 4); // 2 + 2 - assert_eq!(locked_worker.locked_prefix_len(), 2); // Unchanged + assert_eq!(locked_engine.history().len(), 4); // 2 + 2 + assert_eq!(locked_engine.locked_prefix_len(), 2); // Unchanged } /// Verify that turn count is correctly incremented #[tokio::test] -async fn test_turn_count_increment() -> Result<(), WorkerError> { +async fn test_turn_count_increment() -> Result<(), EngineError> { let client = MockLlmClient::with_responses(vec![ vec![ Event::text_block_start(0), @@ -355,21 +355,21 @@ async fn test_turn_count_increment() -> Result<(), WorkerError> { ], ]); - let worker = Worker::new(client); + let engine = Engine::new(client); - assert_eq!(worker.turn_count(), 0); - assert_eq!(worker.llm_call_count(), 0); + assert_eq!(engine.turn_count(), 0); + assert_eq!(engine.llm_call_count(), 0); - // First run consumes Mutable, returns RunOutput - let mut worker = worker.run("First").await?.worker; - assert_eq!(worker.turn_count(), 1); + // First run consumes Mutable, returns EngineRunOutput + let mut engine = engine.run("First").await?.engine; + assert_eq!(engine.turn_count(), 1); // Retry not yet implemented → AgentTurn:LlmCall is 1:1. - assert_eq!(worker.llm_call_count(), 1); + assert_eq!(engine.llm_call_count(), 1); // Subsequent runs on Locked take &mut self - worker.run("Second").await?; - assert_eq!(worker.turn_count(), 2); - assert_eq!(worker.llm_call_count(), 2); + engine.run("Second").await?; + assert_eq!(engine.turn_count(), 2); + assert_eq!(engine.llm_call_count(), 2); Ok(()) } @@ -386,14 +386,14 @@ async fn test_unlock_edit_relock() { }), ]]); - let mut worker = Worker::new(client); - worker.append_history(vec![ + let mut engine = Engine::new(client); + engine.append_history(vec![ Item::user_message("Hello"), Item::assistant_message("Hi"), ]); // Lock -> Unlock - let locked = worker.lock(); + let locked = engine.lock(); assert_eq!(locked.locked_prefix_len(), 2); let mut unlocked = locked.unlock(); @@ -446,11 +446,11 @@ async fn test_lock_unlock_relock_tools_remain_effective() { ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let tool_a = CountingTool::new("tool_a"); - worker.register_tool(tool_a.definition()); + engine.register_tool(tool_a.definition()); - let mut locked = worker.lock(); + let mut locked = engine.lock(); locked.run("first").await.expect("first run"); assert_eq!(tool_a.call_count(), 1, "tool_a should be called once"); @@ -473,9 +473,9 @@ async fn test_lock_unlock_relock_tools_remain_effective() { #[test] fn test_system_prompt_preserved_in_locked_state() { let client = MockLlmClient::new(vec![]); - let worker = Worker::new(client).system_prompt("Important system prompt"); + let engine = Engine::new(client).system_prompt("Important system prompt"); - let locked = worker.lock(); + let locked = engine.lock(); assert_eq!(locked.get_system_prompt(), Some("Important system prompt")); let unlocked = locked.unlock(); @@ -489,9 +489,9 @@ fn test_system_prompt_preserved_in_locked_state() { #[test] fn test_system_prompt_change_after_unlock() { let client = MockLlmClient::new(vec![]); - let worker = Worker::new(client).system_prompt("Original prompt"); + let engine = Engine::new(client).system_prompt("Original prompt"); - let locked = worker.lock(); + let locked = engine.lock(); let mut unlocked = locked.unlock(); unlocked.set_system_prompt("New prompt"); diff --git a/crates/llm-worker/tests/fixtures/anthropic/anthropic_1767624445.jsonl b/crates/llm-engine/tests/fixtures/anthropic/anthropic_1767624445.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/anthropic/anthropic_1767624445.jsonl rename to crates/llm-engine/tests/fixtures/anthropic/anthropic_1767624445.jsonl diff --git a/crates/llm-worker/tests/fixtures/anthropic/simple_text.jsonl b/crates/llm-engine/tests/fixtures/anthropic/simple_text.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/anthropic/simple_text.jsonl rename to crates/llm-engine/tests/fixtures/anthropic/simple_text.jsonl diff --git a/crates/llm-worker/tests/fixtures/anthropic/tool_call.jsonl b/crates/llm-engine/tests/fixtures/anthropic/tool_call.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/anthropic/tool_call.jsonl rename to crates/llm-engine/tests/fixtures/anthropic/tool_call.jsonl diff --git a/crates/llm-worker/tests/fixtures/gemini/long_text.jsonl b/crates/llm-engine/tests/fixtures/gemini/long_text.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/gemini/long_text.jsonl rename to crates/llm-engine/tests/fixtures/gemini/long_text.jsonl diff --git a/crates/llm-worker/tests/fixtures/gemini/simple_text.jsonl b/crates/llm-engine/tests/fixtures/gemini/simple_text.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/gemini/simple_text.jsonl rename to crates/llm-engine/tests/fixtures/gemini/simple_text.jsonl diff --git a/crates/llm-worker/tests/fixtures/gemini/tool_call.jsonl b/crates/llm-engine/tests/fixtures/gemini/tool_call.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/gemini/tool_call.jsonl rename to crates/llm-engine/tests/fixtures/gemini/tool_call.jsonl diff --git a/crates/llm-worker/tests/fixtures/ollama/long_text.jsonl b/crates/llm-engine/tests/fixtures/ollama/long_text.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/ollama/long_text.jsonl rename to crates/llm-engine/tests/fixtures/ollama/long_text.jsonl diff --git a/crates/llm-worker/tests/fixtures/ollama/simple_text.jsonl b/crates/llm-engine/tests/fixtures/ollama/simple_text.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/ollama/simple_text.jsonl rename to crates/llm-engine/tests/fixtures/ollama/simple_text.jsonl diff --git a/crates/llm-worker/tests/fixtures/ollama/tool_call.jsonl b/crates/llm-engine/tests/fixtures/ollama/tool_call.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/ollama/tool_call.jsonl rename to crates/llm-engine/tests/fixtures/ollama/tool_call.jsonl diff --git a/crates/llm-worker/tests/fixtures/openai/long_text.jsonl b/crates/llm-engine/tests/fixtures/openai/long_text.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/openai/long_text.jsonl rename to crates/llm-engine/tests/fixtures/openai/long_text.jsonl diff --git a/crates/llm-worker/tests/fixtures/openai/openai_1767708975.jsonl b/crates/llm-engine/tests/fixtures/openai/openai_1767708975.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/openai/openai_1767708975.jsonl rename to crates/llm-engine/tests/fixtures/openai/openai_1767708975.jsonl diff --git a/crates/llm-worker/tests/fixtures/openai/simple_text.jsonl b/crates/llm-engine/tests/fixtures/openai/simple_text.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/openai/simple_text.jsonl rename to crates/llm-engine/tests/fixtures/openai/simple_text.jsonl diff --git a/crates/llm-worker/tests/fixtures/openai/tool_call.jsonl b/crates/llm-engine/tests/fixtures/openai/tool_call.jsonl similarity index 100% rename from crates/llm-worker/tests/fixtures/openai/tool_call.jsonl rename to crates/llm-engine/tests/fixtures/openai/tool_call.jsonl diff --git a/crates/llm-worker/tests/gemini_fixtures.rs b/crates/llm-engine/tests/gemini_fixtures.rs similarity index 100% rename from crates/llm-worker/tests/gemini_fixtures.rs rename to crates/llm-engine/tests/gemini_fixtures.rs diff --git a/crates/llm-worker/tests/ollama_fixtures.rs b/crates/llm-engine/tests/ollama_fixtures.rs similarity index 100% rename from crates/llm-worker/tests/ollama_fixtures.rs rename to crates/llm-engine/tests/ollama_fixtures.rs diff --git a/crates/llm-worker/tests/openai_fixtures.rs b/crates/llm-engine/tests/openai_fixtures.rs similarity index 100% rename from crates/llm-worker/tests/openai_fixtures.rs rename to crates/llm-engine/tests/openai_fixtures.rs diff --git a/crates/llm-worker/tests/parallel_execution_test.rs b/crates/llm-engine/tests/parallel_execution_test.rs similarity index 88% rename from crates/llm-worker/tests/parallel_execution_test.rs rename to crates/llm-engine/tests/parallel_execution_test.rs index 2000bfa3..d048db3e 100644 --- a/crates/llm-worker/tests/parallel_execution_test.rs +++ b/crates/llm-engine/tests/parallel_execution_test.rs @@ -1,18 +1,18 @@ //! Parallel tool execution tests //! -//! Verify that Worker executes multiple tools in parallel. +//! Verify that Engine executes multiple tools in parallel. use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use async_trait::async_trait; -use llm_worker::Worker; -use llm_worker::interceptor::{ +use llm_engine::Engine; +use llm_engine::interceptor::{ Interceptor, PostToolAction, PreToolAction, ToolCallInfo, ToolResultInfo, }; -use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent}; -use llm_worker::tool::{ +use llm_engine::llm_client::event::{Event, ResponseStatus, StatusEvent}; +use llm_engine::tool::{ Tool, ToolDefinition, ToolError, ToolExecutionContext, ToolMeta, ToolOutput, ToolResult, }; @@ -64,7 +64,7 @@ impl Tool for SlowTool { async fn execute( &self, _input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { self.call_count.fetch_add(1, Ordering::SeqCst); tokio::time::sleep(Duration::from_millis(self.delay_ms)).await; @@ -146,7 +146,7 @@ async fn test_parallel_tool_execution() { }), ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let tool1 = SlowTool::new("slow_tool_1", 100); let tool2 = SlowTool::new("slow_tool_2", 100); let tool3 = SlowTool::new("slow_tool_3", 100); @@ -155,13 +155,13 @@ async fn test_parallel_tool_execution() { let tool2_clone = tool2.clone(); let tool3_clone = tool3.clone(); - worker.register_tool(tool1.definition()); - worker.register_tool(tool2.definition()); - worker.register_tool(tool3.definition()); + engine.register_tool(tool1.definition()); + engine.register_tool(tool2.definition()); + engine.register_tool(tool3.definition()); let start = Instant::now(); - // Mutable::run consumes self, returns (Locked, WorkerResult) - let _result = worker.run("Run all tools").await; + // Mutable::run consumes self, returns (Locked, EngineResult) + let _result = engine.run("Run all tools").await; let elapsed = start.elapsed(); // Verify all tools were called @@ -206,14 +206,14 @@ async fn test_tool_execution_context_order_and_batch_id() { }), ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let contexts = Arc::new(Mutex::new(Vec::new())); - worker.register_tool(ContextRecordingTool::new("record_a", contexts.clone()).definition()); - worker.register_tool(ContextRecordingTool::new("record_b", contexts.clone()).definition()); - worker.register_tool(ContextRecordingTool::new("record_c", contexts.clone()).definition()); + engine.register_tool(ContextRecordingTool::new("record_a", contexts.clone()).definition()); + engine.register_tool(ContextRecordingTool::new("record_b", contexts.clone()).definition()); + engine.register_tool(ContextRecordingTool::new("record_c", contexts.clone()).definition()); - let _ = worker.run("record contexts").await; + let _ = engine.run("record contexts").await; let mut contexts = contexts.lock().unwrap().clone(); contexts.sort_by_key(|ctx| ctx.call_index); @@ -257,12 +257,12 @@ async fn test_tool_execution_context_batch_id_changes_between_batches() { }), ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let contexts = Arc::new(Mutex::new(Vec::new())); - worker.register_tool(ContextRecordingTool::new("record", contexts.clone()).definition()); + engine.register_tool(ContextRecordingTool::new("record", contexts.clone()).definition()); - let _ = worker.run("record batches").await; + let _ = engine.run("record batches").await; let contexts = contexts.lock().unwrap().clone(); assert_eq!(contexts.len(), 2); @@ -299,17 +299,17 @@ async fn test_tool_execution_context_for_skipped_and_synthetic_paths() { }), ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let executed_contexts = Arc::new(Mutex::new(Vec::new())); let pre_contexts = Arc::new(Mutex::new(Vec::new())); let post_contexts = Arc::new(Mutex::new(Vec::new())); - worker + engine .register_tool(ContextRecordingTool::new("record", executed_contexts.clone()).definition()); - worker.register_tool( + engine.register_tool( ContextRecordingTool::new("skip_tool", executed_contexts.clone()).definition(), ); - worker.register_tool( + engine.register_tool( ContextRecordingTool::new("synthetic_tool", executed_contexts.clone()).definition(), ); @@ -341,12 +341,12 @@ async fn test_tool_execution_context_for_skipped_and_synthetic_paths() { } } - worker.set_interceptor(ContextPolicy { + engine.set_interceptor(ContextPolicy { pre_contexts: pre_contexts.clone(), post_contexts: post_contexts.clone(), }); - let _ = worker.run("record skipped and synthetic contexts").await; + let _ = engine.run("record skipped and synthetic contexts").await; let mut pre_contexts = pre_contexts.lock().unwrap().clone(); pre_contexts.sort_by_key(|ctx| ctx.call_index); @@ -390,7 +390,7 @@ async fn test_before_tool_call_skip() { ]; let client = MockLlmClient::new(events); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let allowed_tool = SlowTool::new("allowed_tool", 10); let blocked_tool = SlowTool::new("blocked_tool", 10); @@ -398,8 +398,8 @@ async fn test_before_tool_call_skip() { let allowed_clone = allowed_tool.clone(); let blocked_clone = blocked_tool.clone(); - worker.register_tool(allowed_tool.definition()); - worker.register_tool(blocked_tool.definition()); + engine.register_tool(allowed_tool.definition()); + engine.register_tool(blocked_tool.definition()); // Policy to skip "blocked_tool" struct BlockingPolicy; @@ -415,10 +415,10 @@ async fn test_before_tool_call_skip() { } } - worker.set_interceptor(BlockingPolicy); + engine.set_interceptor(BlockingPolicy); - // Mutable::run consumes self, returns (Locked, WorkerResult) - let _result = worker.run("Test hook").await; + // Mutable::run consumes self, returns (Locked, EngineResult) + let _result = engine.run("Test hook").await; // allowed_tool is called, but blocked_tool is not assert_eq!( @@ -458,7 +458,7 @@ async fn test_post_tool_call_modification() { ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); #[derive(Clone)] struct SimpleTool; @@ -468,7 +468,7 @@ async fn test_post_tool_call_modification() { async fn execute( &self, _: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { Ok("Original Result".to_string().into()) } @@ -483,7 +483,7 @@ async fn test_post_tool_call_modification() { }) } - worker.register_tool(simple_tool_definition()); + engine.register_tool(simple_tool_definition()); // Policy to modify results struct ModifyingPolicy { @@ -500,14 +500,14 @@ async fn test_post_tool_call_modification() { } let modified_content = Arc::new(std::sync::Mutex::new(None)); - worker.set_interceptor(ModifyingPolicy { + engine.set_interceptor(ModifyingPolicy { modified_content: modified_content.clone(), }); - // Mutable::run consumes self, returns (Locked, WorkerResult) - let result = worker.run("Test modification").await; + // Mutable::run consumes self, returns (Locked, EngineResult) + let result = engine.run("Test modification").await; - assert!(result.is_ok(), "Worker should complete"); + assert!(result.is_ok(), "Engine should complete"); // Verify hook was called and content was modified let content = modified_content.lock().unwrap().clone(); @@ -541,10 +541,10 @@ async fn test_before_tool_call_synthetic_result_committed() { }), ], ]); - let mut worker = Worker::new(client); + let mut engine = Engine::new(client); let blocked_tool = SlowTool::new("blocked_tool", 10); let blocked_clone = blocked_tool.clone(); - worker.register_tool(blocked_tool.definition()); + engine.register_tool(blocked_tool.definition()); struct SyntheticPolicy; @@ -558,14 +558,14 @@ async fn test_before_tool_call_synthetic_result_committed() { } } - worker.set_interceptor(SyntheticPolicy); + engine.set_interceptor(SyntheticPolicy); - let result = worker.run("Test synthetic result").await.unwrap(); + let result = engine.run("Test synthetic result").await.unwrap(); assert_eq!(blocked_clone.call_count(), 0, "Blocked tool should not run"); - assert!(result.worker.history().iter().any(|item| matches!( + assert!(result.engine.history().iter().any(|item| matches!( item, - llm_worker::Item::ToolResult { + llm_engine::Item::ToolResult { call_id, summary, is_error: true, diff --git a/crates/llm-worker/tests/reasoning_round_trip_test.rs b/crates/llm-engine/tests/reasoning_round_trip_test.rs similarity index 86% rename from crates/llm-worker/tests/reasoning_round_trip_test.rs rename to crates/llm-engine/tests/reasoning_round_trip_test.rs index 309e036c..fa121d2b 100644 --- a/crates/llm-worker/tests/reasoning_round_trip_test.rs +++ b/crates/llm-engine/tests/reasoning_round_trip_test.rs @@ -1,6 +1,6 @@ //! Reasoning history round-trip 統合テスト //! -//! Worker のストリーム → history append → 次リクエスト送出までの +//! Engine のストリーム → history append → 次リクエスト送出までの //! ライフサイクルで `Item::Reasoning` が脱落せず保持されることを確認する。 //! //! 検証点: @@ -14,9 +14,9 @@ mod common; use common::MockLlmClient; -use llm_worker::Item; -use llm_worker::Worker; -use llm_worker::llm_client::event::{ +use llm_engine::Engine; +use llm_engine::Item; +use llm_engine::llm_client::event::{ BlockMetadata, BlockStart, BlockStop, BlockType, Event, ReasoningBlockData, ResponseStatus, StatusEvent, }; @@ -28,9 +28,9 @@ fn reasoning_block(text: impl Into, data: ReasoningBlockData) -> Vec, data: ReasoningBlockData) -> Vec, Locked>` in the current scope +error[E0599]: no method named `register_tool` found for struct `Engine, Locked>` in the current scope --> tests/ui/locked_register_tool.rs:27:20 | 27 | let _ = locked.register_tool(def); - | ^^^^^^^^^^^^^ method not found in `Worker, Locked>` + | ^^^^^^^^^^^^^ method not found in `Engine, Locked>` | = note: the method was found for - - `Worker` + - `Engine` diff --git a/crates/llm-worker/tests/ui/tool_server_handle_register_tool.rs b/crates/llm-engine/tests/ui/tool_server_handle_register_tool.rs similarity index 64% rename from crates/llm-worker/tests/ui/tool_server_handle_register_tool.rs rename to crates/llm-engine/tests/ui/tool_server_handle_register_tool.rs index 5d710c92..b52db911 100644 --- a/crates/llm-worker/tests/ui/tool_server_handle_register_tool.rs +++ b/crates/llm-engine/tests/ui/tool_server_handle_register_tool.rs @@ -1,9 +1,9 @@ -use llm_worker::Worker; -use llm_worker::llm_client::capability::{ +use llm_engine::Engine; +use llm_engine::llm_client::capability::{ CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport, }; -use llm_worker::llm_client::scheme::anthropic::AnthropicScheme; -use llm_worker::llm_client::transport::{HttpTransport, ResolvedAuth}; +use llm_engine::llm_client::scheme::anthropic::AnthropicScheme; +use llm_engine::llm_client::transport::{HttpTransport, ResolvedAuth}; use std::sync::Arc; fn main() { @@ -21,8 +21,8 @@ fn main() { ResolvedAuth::None, cap, ); - let worker = Worker::new(client); - let handle = worker.tool_server_handle(); - let def: llm_worker::tool::ToolDefinition = Arc::new(|| panic!("unused")); + let engine = Engine::new(client); + let handle = engine.tool_server_handle(); + let def: llm_engine::tool::ToolDefinition = Arc::new(|| panic!("unused")); let _ = handle.register_tool(def); } diff --git a/crates/llm-worker/tests/ui/tool_server_handle_register_tool.stderr b/crates/llm-engine/tests/ui/tool_server_handle_register_tool.stderr similarity index 84% rename from crates/llm-worker/tests/ui/tool_server_handle_register_tool.stderr rename to crates/llm-engine/tests/ui/tool_server_handle_register_tool.stderr index e90a37c4..1d9ee4db 100644 --- a/crates/llm-worker/tests/ui/tool_server_handle_register_tool.stderr +++ b/crates/llm-engine/tests/ui/tool_server_handle_register_tool.stderr @@ -6,5 +6,5 @@ error[E0624]: method `register_tool` is private | ::: src/tool_server.rs | - | pub(crate) fn register_tool(&self, factory: WorkerToolDefinition) { + | pub(crate) fn register_tool(&self, factory: EngineToolDefinition) { | ----------------------------------------------------------------- private method defined here diff --git a/crates/manifest/Cargo.toml b/crates/manifest/Cargo.toml index ceae4a9c..23bbcc90 100644 --- a/crates/manifest/Cargo.toml +++ b/crates/manifest/Cargo.toml @@ -6,7 +6,7 @@ license.workspace = true [dependencies] arc-swap = "1" -llm-worker = { workspace = true } +llm-engine = { workspace = true } mlua = { version = "0.11.4", features = ["lua54", "vendored", "serialize"] } protocol = { workspace = true } serde = { workspace = true, features = ["derive"] } diff --git a/crates/manifest/src/model.rs b/crates/manifest/src/model.rs index 691f8657..08a866bc 100644 --- a/crates/manifest/src/model.rs +++ b/crates/manifest/src/model.rs @@ -14,9 +14,9 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; -// `ModelCapability` は `llm-worker` 側に定義される runtime 構造だが、 +// `ModelCapability` は `llm-engine` 側に定義される runtime 構造だが、 // マニフェストで任意に override できるよう型だけ再エクスポートする。 -pub use llm_worker::llm_client::capability::{ModelCapability, ReasoningControl, ReasoningEffort}; +pub use llm_engine::llm_client::capability::{ModelCapability, ReasoningControl, ReasoningEffort}; /// Pod マニフェストの `[model]` セクション。 /// diff --git a/crates/mcp/tests/stdio_lifecycle.rs b/crates/mcp/tests/stdio_lifecycle.rs index a947c40c..4cb0e8aa 100644 --- a/crates/mcp/tests/stdio_lifecycle.rs +++ b/crates/mcp/tests/stdio_lifecycle.rs @@ -225,7 +225,7 @@ async fn permission_denial_style_shutdown_sends_no_tools_call() { let mut client = McpStdioClient::connect(mock_server("tools-call-forbidden"), tight_limits()) .await .expect("connect"); - // This mirrors Worker pre-tool-call denial: the ordinary Tool execution body + // This mirrors Engine pre-tool-call denial: the ordinary Tool execution body // is never entered, so the MCP server sees lifecycle shutdown but no call. client.shutdown().await.expect("shutdown"); } diff --git a/crates/memory/Cargo.toml b/crates/memory/Cargo.toml index 7a09c0e8..9a37751a 100644 --- a/crates/memory/Cargo.toml +++ b/crates/memory/Cargo.toml @@ -9,7 +9,7 @@ async-trait = { workspace = true } chrono = { version = "0.4", features = ["serde"] } libc = { workspace = true } lint-common = { workspace = true } -llm-worker = { workspace = true } +llm-engine = { workspace = true } manifest = { workspace = true } schemars = { workspace = true } serde = { workspace = true, features = ["derive"] } diff --git a/crates/memory/README.md b/crates/memory/README.md index fbcf9e31..6d4b9ec0 100644 --- a/crates/memory/README.md +++ b/crates/memory/README.md @@ -17,7 +17,7 @@ Owns: Does not own: - authoritative project records (`.yoi/tickets/`, git history) -- normal Pod turn orchestration (`llm-worker`) +- normal Pod turn orchestration (`llm-engine`) - product CLI command shape (`yoi`) - curated workflow definitions (`workflow`) diff --git a/crates/memory/src/consolidate/input.rs b/crates/memory/src/consolidate/input.rs index ec9d6b0f..016e1196 100644 --- a/crates/memory/src/consolidate/input.rs +++ b/crates/memory/src/consolidate/input.rs @@ -1,7 +1,7 @@ -//! consolidation sub-Worker への最初のユーザー入力を組み立てる。 +//! consolidation sub-Engine への最初のユーザー入力を組み立てる。 //! //! extract (`extract::build_extract_input`) と同じ方針で、固定 schema の -//! markdown セクション列にしてサブWorker に渡す。`docs/plan/memory.md` +//! markdown セクション列にしてサブEngine に渡す。`docs/plan/memory.md` //! §Consolidation 入力 / §整理材料 の項目に従い: //! //! 1. consumed staging エントリ全文(`source` 込み) @@ -19,7 +19,7 @@ use crate::consolidate::tidy::TidyHints; use crate::usage::UsageReport; use crate::workspace::{RecordKind, WorkspaceLayout}; -/// consolidation sub-Worker の最初の user 入力。 +/// consolidation sub-Engine の最初の user 入力。 pub fn build_consolidate_input( layout: &WorkspaceLayout, staging: &[StagingEntry], diff --git a/crates/memory/src/consolidate/lock.rs b/crates/memory/src/consolidate/lock.rs index ed3a9ced..af72a184 100644 --- a/crates/memory/src/consolidate/lock.rs +++ b/crates/memory/src/consolidate/lock.rs @@ -147,7 +147,7 @@ impl StagingLock { } /// 占有ファイルだけ削除し、staging エントリには触らない。consolidation - /// sub-Worker が途中で失敗した場合に使う: 入力 staging を残したまま + /// sub-Engine が途中で失敗した場合に使う: 入力 staging を残したまま /// 次回再評価で再処理させる(`docs/plan/memory.md` §並走防止 の /// 「重複作成は同一 slug update に自然収束」運用)。 pub fn release_only(self) { diff --git a/crates/memory/src/consolidate/mod.rs b/crates/memory/src/consolidate/mod.rs index 0aed4d9c..0f4ffb9f 100644 --- a/crates/memory/src/consolidate/mod.rs +++ b/crates/memory/src/consolidate/mod.rs @@ -2,13 +2,13 @@ //! //! extract が staging に残した活動ログを `memory/*` / `knowledge/*` に //! 統合し、続けて既存 record を `outdated | superseded | unused | noisy` -//! の観点で整理する disposable Worker を、Pod 側が組み立てるための -//! ヘルパー群を提供する。Pod は次の手順で sub-Worker を構築する: +//! の観点で整理する disposable Engine を、Pod 側が組み立てるための +//! ヘルパー群を提供する。Pod は次の手順で sub-Engine を構築する: //! -//! - [`build_consolidate_input`] を sub-Worker の最初の user 入力に +//! - [`build_consolidate_input`] を sub-Engine の最初の user 入力に //! - memory 専用 Tool (read / write / edit) と Knowledge / memory 検索ツールを登録 //! - [`StagingLock::acquire`] で並走防止 + consumed ID 確定 -//! - sub-Worker run 完了後、[`StagingLock::release_with_cleanup`] で +//! - sub-Engine run 完了後、[`StagingLock::release_with_cleanup`] で //! consumed ID 分の staging のみ削除し、占有ファイルを解放 //! //! system prompt は Pod の `PromptCatalog` diff --git a/crates/memory/src/extract/input.rs b/crates/memory/src/extract/input.rs index 34820694..ccb22e42 100644 --- a/crates/memory/src/extract/input.rs +++ b/crates/memory/src/extract/input.rs @@ -1,13 +1,13 @@ -//! extract sub-Worker への入力テキスト組み立て。 +//! extract sub-Engine への入力テキスト組み立て。 //! //! `crates/pod/src/pod.rs::build_summary_prompt` と同じ方針で //! Item 列を flat な行に落とす(reasoning は省く、tool call は名前のみ、 //! tool result は summary のみ)。conversation 全体を Markdown の単一 //! セクションとして渡し、抽出指示は system prompt 側に寄せる。 -use llm_worker::Item; +use llm_engine::Item; -/// 与えられた `items` を extract sub-Worker の最初の user 入力に整形する。 +/// 与えられた `items` を extract sub-Engine の最初の user 入力に整形する。 pub fn build_extract_input(items: &[Item]) -> String { let mut out = String::new(); out.push_str( @@ -26,9 +26,9 @@ fn render_items(items: &[Item]) -> String { match item { Item::Message { role, content, .. } => { let role_label = match role { - llm_worker::Role::User => "User", - llm_worker::Role::Assistant => "Assistant", - llm_worker::Role::System => "System", + llm_engine::Role::User => "User", + llm_engine::Role::Assistant => "Assistant", + llm_engine::Role::System => "System", }; let text: String = content .iter() diff --git a/crates/memory/src/extract/mod.rs b/crates/memory/src/extract/mod.rs index fb75e8e6..a4f38921 100644 --- a/crates/memory/src/extract/mod.rs +++ b/crates/memory/src/extract/mod.rs @@ -1,10 +1,10 @@ //! extract: 活動抽出。 //! -//! 通常 Pod の post-run hook で発火する disposable Worker と、その +//! 通常 Pod の post-run hook で発火する disposable Engine と、その //! 出力を `/.yoi/memory/_staging/.json` に書き出す //! ヘルパーを提供する。Pod 側はこのモジュールから: //! -//! - [`build_extract_input`] を sub-Worker の最初の user 入力に +//! - [`build_extract_input`] を sub-Engine の最初の user 入力に //! - [`write_extracted_tool`] を唯一のツールとして //! - [`write_staging`] で受け取った JSON を staging に書き出し //! diff --git a/crates/memory/src/extract/tool.rs b/crates/memory/src/extract/tool.rs index ef0f8c1e..793f011e 100644 --- a/crates/memory/src/extract/tool.rs +++ b/crates/memory/src/extract/tool.rs @@ -1,6 +1,6 @@ -//! `write_extracted` ツール実装と sub-Worker 用 context。 +//! `write_extracted` ツール実装と sub-Engine 用 context。 //! -//! sub-Worker からは extract worker が出した [`ExtractedPayload`] を +//! sub-Engine からは extract worker が出した [`ExtractedPayload`] を //! 受け取って `Mutex` 越しに [`ExtractWorkerContext`] に置くだけ。 //! Pod 側はランループ完了後に `take_payload()` で取り出して //! [`super::staging::write_staging`] に渡す。 @@ -8,7 +8,7 @@ use std::sync::{Arc, Mutex}; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use crate::extract::payload::ExtractedPayload; @@ -17,7 +17,7 @@ Pass an object with `decisions`, `discussions`, `attempts`, and `requests` array Call this exactly once and end the turn. Do not include `source`, session metadata, or free-form prose — \ the wrapper attaches provenance mechanically."; -/// extract sub-Worker の出力受け口。`ExtractedPayload` 1 件をホストする。 +/// extract sub-Engine の出力受け口。`ExtractedPayload` 1 件をホストする。 #[derive(Debug, Default)] pub struct ExtractWorkerContext { payload: Mutex>, @@ -31,7 +31,7 @@ impl ExtractWorkerContext { Self::default() } - /// sub-Worker 終了後に Pod が呼んで payload を取り出す。 + /// sub-Engine 終了後に Pod が呼んで payload を取り出す。 /// 一度も `write_extracted` が呼ばれなければ `None`。 pub fn take_payload(&self) -> Option { self.payload @@ -57,7 +57,7 @@ impl Tool for WriteExtractedTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let payload: ExtractedPayload = serde_json::from_str(input_json).map_err(|e| { ToolError::InvalidArgument(format!("invalid write_extracted input: {e}")) @@ -92,7 +92,7 @@ impl Tool for WriteExtractedTool { } } -/// sub-Worker に register する `write_extracted` ツール定義を返す。 +/// sub-Engine に register する `write_extracted` ツール定義を返す。 pub fn write_extracted_tool(ctx: Arc) -> ToolDefinition { Arc::new(move || { let schema = schemars::schema_for!(ExtractedPayload); @@ -109,7 +109,7 @@ pub fn write_extracted_tool(ctx: Arc) -> ToolDefinition { mod tests { use super::*; - use llm_worker::tool::Tool; + use llm_engine::tool::Tool; #[tokio::test] async fn write_extracted_records_payload() { diff --git a/crates/memory/src/tool/delete.rs b/crates/memory/src/tool/delete.rs index 1e36aa85..12364608 100644 --- a/crates/memory/src/tool/delete.rs +++ b/crates/memory/src/tool/delete.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use crate::audit::{AuditStatus, RecordOperationAudit, append_record_operation, file_hash}; @@ -32,7 +32,7 @@ impl Tool for MemoryDeleteTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: DeleteParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid MemoryDelete input: {e}")))?; diff --git a/crates/memory/src/tool/edit.rs b/crates/memory/src/tool/edit.rs index dc495e3c..1b69d006 100644 --- a/crates/memory/src/tool/edit.rs +++ b/crates/memory/src/tool/edit.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use crate::audit::{ @@ -50,7 +50,7 @@ impl Tool for EditTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: EditParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid MemoryEdit input: {e}")))?; diff --git a/crates/memory/src/tool/mod.rs b/crates/memory/src/tool/mod.rs index bcd8192b..c661f1a4 100644 --- a/crates/memory/src/tool/mod.rs +++ b/crates/memory/src/tool/mod.rs @@ -15,7 +15,7 @@ pub use delete::delete_tool; use std::path::PathBuf; -use llm_worker::tool::ToolError; +use llm_engine::tool::ToolError; use serde::Deserialize; use crate::Slug; @@ -27,7 +27,7 @@ pub use read::{read_tool, read_tool_with_usage}; pub use write::write_tool; /// Kinds the memory tools accept as input. `Workflow` is intentionally -/// excluded — workflows are sub-Worker context, not agent-editable. +/// excluded — workflows are sub-Engine context, not agent-editable. #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "lowercase")] pub enum MemoryToolKind { diff --git a/crates/memory/src/tool/query.rs b/crates/memory/src/tool/query.rs index 041882c8..da92c3a3 100644 --- a/crates/memory/src/tool/query.rs +++ b/crates/memory/src/tool/query.rs @@ -21,7 +21,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::{Deserialize, Serialize}; use crate::audit::{AuditStatus, RecordUsageAudit, append_record_usage}; @@ -129,7 +129,7 @@ impl Tool for MemoryQueryTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: MemoryQueryParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid MemoryQuery input: {e}")))?; @@ -247,7 +247,7 @@ impl Tool for KnowledgeQueryTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: KnowledgeQueryParams = serde_json::from_str(input_json).map_err(|e| { ToolError::InvalidArgument(format!("invalid KnowledgeQuery input: {e}")) diff --git a/crates/memory/src/tool/read.rs b/crates/memory/src/tool/read.rs index 9a65f5fe..a29badfd 100644 --- a/crates/memory/src/tool/read.rs +++ b/crates/memory/src/tool/read.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use crate::audit::{AuditStatus, RecordUsageAudit, append_record_usage}; @@ -48,7 +48,7 @@ impl Tool for ReadTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: ReadParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid MemoryRead input: {e}")))?; diff --git a/crates/memory/src/tool/write.rs b/crates/memory/src/tool/write.rs index 8635f4ad..f4ce1926 100644 --- a/crates/memory/src/tool/write.rs +++ b/crates/memory/src/tool/write.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use crate::audit::{ @@ -45,7 +45,7 @@ impl Tool for WriteTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: WriteParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid MemoryWrite input: {e}")))?; diff --git a/crates/plugin-pdk/tests/template.rs b/crates/plugin-pdk/tests/template.rs index 82b8ff13..12689f1c 100644 --- a/crates/plugin-pdk/tests/template.rs +++ b/crates/plugin-pdk/tests/template.rs @@ -179,7 +179,7 @@ fn pdk_runtime_dependencies_are_guest_side_only() { let forbidden = [ "pod", "yoi-pod", - "llm-worker", + "llm-engine", "tui", "yoi-tui", "client", diff --git a/crates/pod-store/README.md b/crates/pod-store/README.md index ecd84634..4718033e 100644 --- a/crates/pod-store/README.md +++ b/crates/pod-store/README.md @@ -19,7 +19,7 @@ Does not own: - replayable conversation logs (`session-store`) - live process locks or socket reachability (`pod-registry`, `client`) - product CLI behavior (`yoi`) -- model turn execution (`llm-worker`) +- model turn execution (`llm-engine`) ## Design notes diff --git a/crates/pod/Cargo.toml b/crates/pod/Cargo.toml index 900abc08..851a204a 100644 --- a/crates/pod/Cargo.toml +++ b/crates/pod/Cargo.toml @@ -8,7 +8,7 @@ autobins = false [dependencies] async-trait = { workspace = true } clap = { version = "4.6.0", features = ["derive"] } -llm-worker = { workspace = true } +llm-engine = { workspace = true } session-store = { workspace = true } pod-store = { workspace = true } manifest = { workspace = true } diff --git a/crates/pod/README.md b/crates/pod/README.md index 7a337c99..6240c752 100644 --- a/crates/pod/README.md +++ b/crates/pod/README.md @@ -2,21 +2,21 @@ ## Role -`pod` turns an `llm-worker` Worker into a named runtime entity with manifest configuration, scoped tools, session persistence, protocol handling, and Pod metadata integration. +`pod` turns an `llm-engine` Engine into a named runtime entity with manifest configuration, scoped tools, session persistence, protocol handling, and Pod metadata integration. ## Boundaries Owns: - Pod lifecycle and socket protocol serving -- Worker construction around a resolved Manifest +- Engine construction around a resolved Manifest - session-store and pod-store coordination - built-in tool registration under scope/policy - spawned-child orchestration hooks Does not own: -- provider-specific wire formats (`provider` / `llm-worker` clients) +- provider-specific wire formats (`provider` / `llm-engine` clients) - product CLI parsing (`yoi`) - TUI display authority (`tui`) - current-state storage schema outside Pod metadata (`pod-store`) diff --git a/crates/pod/examples/pod_cli.rs b/crates/pod/examples/pod_cli.rs index ed4dd9a2..3b48fb34 100644 --- a/crates/pod/examples/pod_cli.rs +++ b/crates/pod/examples/pod_cli.rs @@ -70,7 +70,7 @@ async fn main() -> Result<(), Box> { } // 5. Extract the assistant's reply from history - let history = pod.worker().history(); + let history = pod.engine().history(); if let Some(text) = history .iter() .rev() diff --git a/crates/pod/src/active_workflow.rs b/crates/pod/src/active_workflow.rs index b682463c..8f4037ce 100644 --- a/crates/pod/src/active_workflow.rs +++ b/crates/pod/src/active_workflow.rs @@ -8,8 +8,8 @@ use std::collections::BTreeMap; use std::sync::{Arc, Mutex}; use async_trait::async_trait; -use llm_worker::Item; -use llm_worker::tool::{ +use llm_engine::Item; +use llm_engine::tool::{ Tool, ToolDefinition, ToolError, ToolExecutionContext, ToolMeta, ToolOutput, }; use serde::{Deserialize, Serialize}; @@ -308,7 +308,7 @@ fn has_active_workflow_hint(item: &Item) -> bool { fn item_system_text(item: &Item) -> Option { match item { - Item::Message { role, content, .. } if *role == llm_worker::Role::System => Some( + Item::Message { role, content, .. } if *role == llm_engine::Role::System => Some( content .iter() .map(|part| part.as_text()) diff --git a/crates/pod/src/compact/metrics_tracker.rs b/crates/pod/src/compact/metrics_tracker.rs index 10feaf1d..02fc756c 100644 --- a/crates/pod/src/compact/metrics_tracker.rs +++ b/crates/pod/src/compact/metrics_tracker.rs @@ -1,5 +1,5 @@ //! Sync buffer for `session_metrics::Metric` values queued from inside -//! Worker callbacks (which run synchronously and cannot themselves +//! Engine callbacks (which run synchronously and cannot themselves //! perform `async` store writes). //! //! Pod drains this buffer in `persist_turn` and writes each metric via diff --git a/crates/pod/src/compact/prune.rs b/crates/pod/src/compact/prune.rs index f4beb679..9fdb277f 100644 --- a/crates/pod/src/compact/prune.rs +++ b/crates/pod/src/compact/prune.rs @@ -1,19 +1,19 @@ -//! Prune integration — wires the Worker's prune projection to the Pod's +//! Prune integration — wires the Engine's prune projection to the Pod's //! usage-history-backed token accounting. //! -//! Worker 自身がコンテキスト射影を行う(`worker.rs` の `request_context` 構築 -//! 直後)。Worker は usage 履歴を知らないので、`min_savings` 判定に使う savings +//! Engine 自身がコンテキスト射影を行う(`worker.rs` の `request_context` 構築 +//! 直後)。Engine は usage 履歴を知らないので、`min_savings` 判定に使う savings //! の見積もりはコールバックで外部から注入する。このモジュールはそのコールバック -//! を組み立てて Worker に差し込むための `impl Pod` を提供する。 +//! を組み立てて Engine に差し込むための `impl Pod` を提供する。 //! //! 同じ経路で `PruneObserver` も install し、評価のたびに `prune.fire` / //! `prune.skip` metric を `MetricsTracker` に積む。`Fired` 時は uuid を //! `UsageTracker` にも stash しておき、後続の `LlmUsage` と組で //! `prune.post_request` を吐けるようにする。 -use llm_worker::Item; -use llm_worker::llm_client::client::LlmClient; -use llm_worker::prune::{ +use llm_engine::Item; +use llm_engine::llm_client::client::LlmClient; +use llm_engine::prune::{ PruneConfig, PruneDecision, PruneObserver, SavingsEstimator, TokenEstimator, }; use session_metrics::Metric; @@ -25,9 +25,9 @@ use crate::compact::token_counter::{ }; impl Pod { - /// Enable prune projection on the underlying Worker. + /// Enable prune projection on the underlying Engine. /// - /// Registers the config and token/savings-estimator closures on the Worker. + /// Registers the config and token/savings-estimator closures on the Engine. /// The estimators combine persisted [`Pod::usage_history_handle`] records /// with in-flight `UsageTracker` records so multi-request tool loops can /// prune before the surrounding Pod run finishes. @@ -100,7 +100,7 @@ impl Pod { } }); - let worker = self.worker_mut(); + let worker = self.engine_mut(); worker.set_prune_config(Some(config)); worker.set_token_estimator(Some(token_estimator)); worker.set_savings_estimator(Some(estimator)); diff --git a/crates/pod/src/compact/token_counter.rs b/crates/pod/src/compact/token_counter.rs index aa843764..8246e3fb 100644 --- a/crates/pod/src/compact/token_counter.rs +++ b/crates/pod/src/compact/token_counter.rs @@ -1,7 +1,7 @@ //! Compact / prune 専用のトークン会計補助。 //! //! 汎用部分(`prefix_bytes`, `tokens_at`, `total_tokens`, `total_tokens_at`)は -//! [`llm_worker::token_counter`] にあり、`UsageRecord` の列と現在の history から +//! [`llm_engine::token_counter`] にあり、`UsageRecord` の列と現在の history から //! pure に推定する。本モジュールは compact / prune 固有のロジック //! (`split_for_retained`, `savings_for_prune`)と、Pod 上の公開 API に //! 限定する。 @@ -17,12 +17,12 @@ //! - 推定の出どころは [`EstimateSource`] で呼び出し側に明示する。 //! 課金判断には使えないが、compact / prune の閾値判定には十分な精度 -use llm_worker::llm_client::client::LlmClient; -use llm_worker::token_counter::{item_bytes, prefix_bytes, tokens_at}; -use llm_worker::{Item, UsageRecord}; +use llm_engine::llm_client::client::LlmClient; +use llm_engine::token_counter::{item_bytes, prefix_bytes, tokens_at}; +use llm_engine::{Item, UsageRecord}; use session_store::Store; -pub use llm_worker::token_counter::{EstimateSource, TokenEstimate}; +pub use llm_engine::token_counter::{EstimateSource, TokenEstimate}; use crate::Pod; @@ -188,7 +188,7 @@ pub(crate) fn token_estimates_for_prune_impl( /// Prune 射影(`ToolResult.content = None`)で節約されるトークン数の推定。 /// -/// `indices` は [`llm_worker::prune::prunable_indices`] が返す候補列を +/// `indices` は [`llm_engine::prune::prunable_indices`] が返す候補列を /// 想定する。各候補の content バイト差分を合算し、usage 履歴由来の /// tokens/byte レートでトークン数に換算する。範囲を「丸ごと drop」する /// のではなく、item 自体(summary 等)は残したままの値を返す点が @@ -248,7 +248,7 @@ impl Pod { /// 最後の measurement と、その後に追加された未測定分の byte/4 外挿。 pub fn total_tokens(&self) -> TokenEstimate { let usage = self.usage_history(); - llm_worker::token_counter::total_tokens(self.history(), &usage) + llm_engine::token_counter::total_tokens(self.history(), &usage) } /// 任意の history index 時点でのプロンプト全長推定。 @@ -259,7 +259,7 @@ impl Pod { /// pointer 以降に増えたプロンプト長を測るのに使う。 pub fn total_tokens_at(&self, history_len: usize) -> TokenEstimate { let usage = self.usage_history(); - llm_worker::token_counter::total_tokens_at(self.history(), &usage, history_len) + llm_engine::token_counter::total_tokens_at(self.history(), &usage, history_len) } /// 末尾から `retained` トークン以上を残すための分割位置。 diff --git a/crates/pod/src/compact/usage_tracker.rs b/crates/pod/src/compact/usage_tracker.rs index e830369a..0963e5b3 100644 --- a/crates/pod/src/compact/usage_tracker.rs +++ b/crates/pod/src/compact/usage_tracker.rs @@ -1,6 +1,6 @@ //! Tracks per-LLM-request Usage measurements within a Pod run. //! -//! Bridge between two sync touchpoints in the Worker lifecycle: +//! Bridge between two sync touchpoints in the Engine lifecycle: //! //! - **`pre_llm_request` hook** (async, but synchronously accessed via the //! tracker): captures `history.len()` at the moment a request goes out. @@ -16,8 +16,8 @@ use std::sync::Mutex; -use llm_worker::UsageRecord; -use llm_worker::timeline::event::UsageEvent; +use llm_engine::UsageRecord; +use llm_engine::timeline::event::UsageEvent; /// One drained measurement: the underlying `UsageRecord` plus an optional /// `correlation_id` stamped by the prune projection (or any other future diff --git a/crates/pod/src/compact/worker.rs b/crates/pod/src/compact/worker.rs index b74d6f59..68cdc4af 100644 --- a/crates/pod/src/compact/worker.rs +++ b/crates/pod/src/compact/worker.rs @@ -1,6 +1,6 @@ //! Compact worker state and the four tools that drive it. //! -//! The compact worker is a disposable `Worker` instance spun up by +//! The compact worker is a disposable `Engine` instance spun up by //! [`Pod::compact`]. It receives the history to summarise plus a list of //! default reference files (from the session-lifetime `Tracker`) and runs //! a tool-driven LLM loop. The tools here let it: @@ -22,9 +22,9 @@ use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::{Arc, Mutex}; use async_trait::async_trait; -use llm_worker::Item; -use llm_worker::interceptor::{Interceptor, PreRequestAction, PreToolAction, ToolCallInfo}; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput, ToolResult}; +use llm_engine::Item; +use llm_engine::interceptor::{Interceptor, PreRequestAction, PreToolAction, ToolCallInfo}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput, ToolResult}; use serde::Deserialize; use tools::ScopedFs; @@ -154,7 +154,7 @@ impl Tool for SearchSessionLogTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: SearchSessionParams = serde_json::from_str(input_json).map_err(|e| { ToolError::InvalidArgument(format!("invalid search_session_log input: {e}")) @@ -213,7 +213,7 @@ impl Tool for ReadSessionItemsTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: ReadSessionParams = serde_json::from_str(input_json).map_err(|e| { ToolError::InvalidArgument(format!("invalid read_session_items input: {e}")) @@ -379,7 +379,7 @@ impl Tool for MarkReadRequiredTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: MarkParams = serde_json::from_str(input_json).map_err(|e| { ToolError::InvalidArgument(format!("invalid mark_read_required input: {e}")) @@ -440,7 +440,7 @@ impl Tool for AddReferenceTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: ReferenceParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid add_reference input: {e}")))?; @@ -468,7 +468,7 @@ impl Tool for WriteSummaryTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: SummaryParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid write_summary input: {e}")))?; @@ -623,7 +623,7 @@ impl CompactWorkerInterceptor { impl Interceptor for CompactWorkerInterceptor { async fn pre_llm_request(&self, context: &mut Vec) -> PreRequestAction { let records = self.usage_tracker.records(); - let estimate = llm_worker::token_counter::total_tokens(context, &records); + let estimate = llm_engine::token_counter::total_tokens(context, &records); if estimate.tokens > self.max_input_tokens { return PreRequestAction::Cancel(format!( "compact worker input occupancy exceeded {} tokens", @@ -673,8 +673,8 @@ mod tests { ScopedFs::new(scope, tmp.to_path_buf()) } - fn make_usage(input: u64) -> llm_worker::timeline::event::UsageEvent { - llm_worker::timeline::event::UsageEvent { + fn make_usage(input: u64) -> llm_engine::timeline::event::UsageEvent { + llm_engine::timeline::event::UsageEvent { input_tokens: Some(input), output_tokens: Some(0), total_tokens: Some(input), diff --git a/crates/pod/src/controller.rs b/crates/pod/src/controller.rs index c9115c6a..ac6854d0 100644 --- a/crates/pod/src/controller.rs +++ b/crates/pod/src/controller.rs @@ -2,8 +2,8 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::sync::atomic::Ordering; -use llm_worker::WorkerError; -use llm_worker::llm_client::client::LlmClient; +use llm_engine::EngineError; +use llm_engine::llm_client::client::LlmClient; use manifest::TicketFeatureAccessConfig; use pod_store::PodMetadataStore; use session_store::Store; @@ -217,7 +217,7 @@ impl PodController { // === 1.5. Direct writer wiring === // - // Worker callbacks fire `on_history_append` for each assistant + // Engine callbacks fire `on_history_append` for each assistant // item / tool result that lands in history. With the sync // writer in place, the callback commits each item directly // through a `LogWriterHandle` (no mpsc ferry, no drain task). @@ -228,8 +228,8 @@ impl PodController { pod.attach_log_writer(writer_for_system); pod.wire_history_persistence(); - // === 2. Worker event bridge wiring === - wire_event_bridges_on_worker(&mut pod, &event_tx, &alerter, &in_flight); + // === 2. Engine event bridge wiring === + wire_event_bridges_on_engine(&mut pod, &event_tx, &alerter, &in_flight); // === 3. Tool registration (builtin / memory / spawn-orchestration) === let fs_for_view = register_pod_tools( @@ -259,7 +259,7 @@ impl PodController { // Materialise pending tool factories so the greeting reflects // the actual registered set instead of a hand-maintained mirror. - pod.worker().tool_server_handle().flush_pending(); + pod.engine().tool_server_handle().flush_pending(); // === 4. Initial runtime files + PodSharedState + PodHandle + // SocketServer === @@ -303,7 +303,7 @@ impl PodController { // Clone cancel sender and notification buffer before moving pod // into the controller task so the in-flight turn can be reached // via these handles while pod itself is borrowed by drive_turn. - let cancel_tx = pod.worker_mut().cancel_sender(); + let cancel_tx = pod.engine_mut().cancel_sender(); let notify_buffer = pod.notify_buffer_handle(); tokio::spawn(controller_loop( @@ -326,7 +326,7 @@ impl PodController { } } -/// Wire the per-event broadcast bridges on the Pod's Worker. Each callback +/// Wire the per-event broadcast bridges on the Pod's Engine. Each callback /// re-publishes a worker-level signal as a `protocol::Event` on `event_tx` /// so subscribers (TUI, socket clients) get a single typed stream. /// @@ -334,7 +334,7 @@ impl PodController { /// per-item history commit callback so every assistant / tool item /// landing in `worker.history` becomes a singular `LogEntry::AssistantItem` /// / `ToolResult` commit through the sync writer. -fn wire_event_bridges_on_worker( +fn wire_event_bridges_on_engine( pod: &mut Pod, event_tx: &broadcast::Sender, alerter: &Alerter, @@ -344,7 +344,7 @@ fn wire_event_bridges_on_worker( St: Store + PodMetadataStore + Clone + 'static, { let ai_activity = pod.ai_activity_counter(); - let worker = pod.worker_mut(); + let worker = pod.engine_mut(); let tx = event_tx.clone(); worker.on_turn_start(move |turn| { @@ -486,7 +486,7 @@ fn wire_event_bridges_on_worker( let alerter_for_worker = alerter.clone(); worker.on_warning(move |message| { - alerter_for_worker.alert(AlertLevel::Warn, AlertSource::Worker, message.to_owned()); + alerter_for_worker.alert(AlertLevel::Warn, AlertSource::Engine, message.to_owned()); }); // History-append broadcasts (previously `Event::SystemMessage`) @@ -575,7 +575,7 @@ fn is_ticket_orchestrator_role(role: Option<&str>) -> bool { /// Register the builtin file-manipulation tools, optional memory tools, /// and the Pod-orchestration tools (SpawnPod + comm) on the Pod's -/// Worker. Returns the `ScopedFs` clone used to attach a `PodFsView` to +/// Engine. Returns the `ScopedFs` clone used to attach a `PodFsView` to /// the shared state. async fn register_pod_tools( pod: &mut Pod, @@ -616,13 +616,13 @@ where // a clone for the FS view we attach below, since the tools consume // `fs` itself. let fs_for_view = fs.clone(); - pod.worker_mut().register_tools(tools::core_builtin_tools( + pod.engine_mut().register_tools(tools::core_builtin_tools( fs, tracker.clone(), bash_output_dir, )); if feature_config.web.enabled { - pod.worker_mut() + pod.engine_mut() .register_tools(tools::web_builtin_tools(web_config)); } @@ -663,7 +663,7 @@ where } { - let worker = pod.worker_mut(); + let worker = pod.engine_mut(); // Memory tools require both explicit feature exposure and memory storage // configuration. This keeps resident-memory config separate from the @@ -777,8 +777,8 @@ async fn controller_loop( // Cancellation is meaningful only for an accepted running turn. Clear // idle/stale signals before the status flip; any Cancel/Pause received // after this point is delivered to the turn and must not be discarded by - // the Worker at run start. - pod.worker_mut().clear_pending_cancel(); + // the Engine at run start. + pod.engine_mut().clear_pending_cancel(); set_controller_status(&shared_state, &runtime_dir, &event_tx, PodStatus::Running).await; let parent_originated = run.is_parent_originated(); let (new_status, shutdown) = match run { @@ -1211,7 +1211,7 @@ where } (status, shutdown_requested) } - Err(PodError::Worker(WorkerError::Cancelled)) if pause_requested => { + Err(PodError::Engine(EngineError::Cancelled)) if pause_requested => { // User-initiated Pause. Report the transition to // clients as a normal Paused run-end, and // intentionally skip `PodEvent::Errored` upward: @@ -1405,10 +1405,10 @@ where ), }; // Tool list reflects whatever `spawn()` ended up registering on the - // Worker. Caller must have flushed pending factories first; without + // Engine. Caller must have flushed pending factories first; without // a flush the tool table is empty and this returns an empty vec. let tool_names: Vec = pod - .worker() + .engine() .tool_server_handle() .tool_definitions_sorted() .into_iter() @@ -1428,9 +1428,9 @@ where fn worker_error_code(e: &PodError) -> ErrorCode { match e { - PodError::Worker(we) => match we { - WorkerError::Tool(_) => ErrorCode::ToolError, - WorkerError::Client(_) => ErrorCode::ProviderError, + PodError::Engine(we) => match we { + EngineError::Tool(_) => ErrorCode::ToolError, + EngineError::Client(_) => ErrorCode::ProviderError, _ => ErrorCode::Internal, }, PodError::Provider(_) => ErrorCode::ProviderError, @@ -1628,7 +1628,7 @@ mod tests { let recv = tokio::spawn(recv_pod_event(listener, Duration::from_secs(2))); let pod_future = async { - Err::(PodError::Worker(WorkerError::Aborted( + Err::(PodError::Engine(EngineError::Aborted( "boom from test".into(), ))) }; @@ -1663,7 +1663,7 @@ mod tests { let listener = UnixListener::bind(&env.parent_socket_path).expect("bind listener"); let pod_future = async { - Err::(PodError::Worker(WorkerError::Aborted( + Err::(PodError::Engine(EngineError::Aborted( "boom from notify".into(), ))) }; diff --git a/crates/pod/src/discovery.rs b/crates/pod/src/discovery.rs index 254d90ea..73168d18 100644 --- a/crates/pod/src/discovery.rs +++ b/crates/pod/src/discovery.rs @@ -16,7 +16,7 @@ use std::time::Duration; use async_trait::async_trait; use client::PodRuntimeCommand; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use manifest::{Permission, ScopeRule}; use pod_store::{PodActiveSegmentRef, PodMetadata, PodMetadataStore, validate_pod_name}; use protocol::stream::JsonLineReader; @@ -845,7 +845,7 @@ where async fn execute( &self, _input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let items = self .discovery @@ -872,7 +872,7 @@ where async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: PodNameInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid RestorePod input: {e}")))?; @@ -948,7 +948,7 @@ where async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: SendToPeerPodInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid SendToPeerPod input: {e}")))?; diff --git a/crates/pod/src/feature.rs b/crates/pod/src/feature.rs index 80ab9549..fcc4eaa1 100644 --- a/crates/pod/src/feature.rs +++ b/crates/pod/src/feature.rs @@ -3,11 +3,11 @@ //! This module defines the Pod-side feature boundary used to collect //! descriptor metadata, tool contributions, safe hook contributions, background //! task declarations, service declarations, and protocol-backed provider -//! startup discovery before installing them into the existing Worker/HookRegistry +//! startup discovery before installing them into the existing Engine/HookRegistry //! host surfaces. //! //! The implementation is intentionally host-mediated: tools are installed through -//! the normal Worker tool path, hooks are installed through +//! the normal Engine tool path, hooks are installed through //! [`crate::hook::HookRegistryBuilder`], and provider output is represented as //! ordinary feature reports/diagnostics instead of a separate authority layer. @@ -15,10 +15,10 @@ use std::collections::{HashMap, HashSet}; use std::fmt; use std::sync::Arc; -use llm_worker::Worker; -use llm_worker::llm_client::client::LlmClient; -use llm_worker::state::Mutable; -use llm_worker::tool::ToolDefinition; +use llm_engine::Engine; +use llm_engine::llm_client::client::LlmClient; +use llm_engine::state::Mutable; +use llm_engine::tool::ToolDefinition; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -167,9 +167,9 @@ impl ProtocolProviderLifecycleDiagnostic { /// Startup-discovered contribution set returned by a protocol-backed provider. /// /// Tool definitions are materialized exactly once when registered, then inserted -/// into the normal Worker tool path as stable metadata plus executable tool +/// into the normal Engine tool path as stable metadata plus executable tool /// handles for the remainder of the run. Execution still flows through the -/// Worker, permission, history, and bounded-result machinery. +/// Engine, permission, history, and bounded-result machinery. #[derive(Clone)] pub struct ProtocolProviderContribution { declaration: ProtocolProviderDeclaration, @@ -1285,10 +1285,10 @@ impl FeatureRegistryBuilder { .collect() } - /// Install modules into the existing Worker tool path and hook builder. - pub(crate) fn install_into_worker( + /// Install modules into the existing Engine tool path and hook builder. + pub(crate) fn install_into_engine( self, - worker: &mut Worker, + worker: &mut Engine, hook_builder: &mut HookRegistryBuilder, ) -> FeatureRegistryInstallReport { let mut pending_tools = Vec::new(); @@ -1485,8 +1485,8 @@ mod tests { use super::*; use async_trait::async_trait; use futures::stream; - use llm_worker::llm_client::{ClientError, Request, ResponseStream}; - use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; + use llm_engine::llm_client::{ClientError, Request, ResponseStream}; + use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde_json::json; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -1511,7 +1511,7 @@ mod tests { async fn execute( &self, _input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { Ok(ToolOutput::from("ok".to_string())) } @@ -1695,7 +1695,7 @@ mod tests { let descriptor = FeatureDescriptor::builtin("provider-feature", "Provider feature") .with_protocol_provider(provider.clone()); let calls = Arc::new(AtomicUsize::new(0)); - let mut worker = Worker::new(DummyClient); + let mut worker = Engine::new(DummyClient); let mut hook_builder = HookRegistryBuilder::default(); let report = FeatureRegistryBuilder::new() @@ -1705,7 +1705,7 @@ mod tests { calls: Arc::clone(&calls), state: ProtocolProviderLifecycleState::Ready, }) - .install_into_worker(&mut worker, &mut hook_builder); + .install_into_engine(&mut worker, &mut hook_builder); worker.tool_server_handle().flush_pending(); let tool_names: Vec<_> = worker @@ -1848,13 +1848,13 @@ mod tests { } let calls = Arc::new(AtomicUsize::new(0)); - let mut worker = Worker::new(DummyClient); + let mut worker = Engine::new(DummyClient); let mut hook_builder = HookRegistryBuilder::default(); let report = FeatureRegistryBuilder::new() .with_module(StatefulToolFeature { calls: Arc::clone(&calls), }) - .install_into_worker(&mut worker, &mut hook_builder); + .install_into_engine(&mut worker, &mut hook_builder); worker.tool_server_handle().flush_pending(); let names: Vec<_> = worker @@ -2220,11 +2220,11 @@ mod tests { #[test] fn builtin_task_feature_installs_through_worker_tool_path() { - let mut worker = Worker::new(DummyClient); + let mut worker = Engine::new(DummyClient); let mut hook_builder = HookRegistryBuilder::default(); let report = FeatureRegistryBuilder::new() .with_module(builtin::task_tools_feature()) - .install_into_worker(&mut worker, &mut hook_builder); + .install_into_engine(&mut worker, &mut hook_builder); worker.tool_server_handle().flush_pending(); let names: Vec<_> = worker diff --git a/crates/pod/src/feature/builtin/task/mod.rs b/crates/pod/src/feature/builtin/task/mod.rs index abf6741d..c9be5f8d 100644 --- a/crates/pod/src/feature/builtin/task/mod.rs +++ b/crates/pod/src/feature/builtin/task/mod.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use async_trait::async_trait; -use llm_worker::Item; +use llm_engine::Item; mod store; mod tool_impl; diff --git a/crates/pod/src/feature/builtin/task/store.rs b/crates/pod/src/feature/builtin/task/store.rs index dee5e53c..3259e24f 100644 --- a/crates/pod/src/feature/builtin/task/store.rs +++ b/crates/pod/src/feature/builtin/task/store.rs @@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex}; -use llm_worker::Item; +use llm_engine::Item; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] diff --git a/crates/pod/src/feature/builtin/task/tool_impl.rs b/crates/pod/src/feature/builtin/task/tool_impl.rs index 40d1adf4..c06f5fe2 100644 --- a/crates/pod/src/feature/builtin/task/tool_impl.rs +++ b/crates/pod/src/feature/builtin/task/tool_impl.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use super::store::{TaskEntry, TaskStatus, TaskStore, render_snapshot, snapshot_overview}; @@ -76,7 +76,7 @@ impl Tool for TaskCreateTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TaskCreateParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid TaskCreate input: {e}")))?; @@ -100,7 +100,7 @@ impl Tool for TaskListTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let _: TaskListParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid TaskList input: {e}")))?; @@ -117,7 +117,7 @@ impl Tool for TaskGetTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TaskGetParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid TaskGet input: {e}")))?; @@ -137,7 +137,7 @@ impl Tool for TaskUpdateTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TaskUpdateParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid TaskUpdate input: {e}")))?; diff --git a/crates/pod/src/feature/builtin/ticket.rs b/crates/pod/src/feature/builtin/ticket.rs index c3bfd804..20c33029 100644 --- a/crates/pod/src/feature/builtin/ticket.rs +++ b/crates/pod/src/feature/builtin/ticket.rs @@ -256,7 +256,7 @@ mod tests { } fn pending_tool_description( - pending_tools: &[llm_worker::tool::ToolDefinition], + pending_tools: &[llm_engine::tool::ToolDefinition], name: &str, ) -> String { pending_tools diff --git a/crates/pod/src/feature/mcp.rs b/crates/pod/src/feature/mcp.rs index 5b61c025..ce1d4869 100644 --- a/crates/pod/src/feature/mcp.rs +++ b/crates/pod/src/feature/mcp.rs @@ -3,7 +3,7 @@ use std::path::Path; use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{ +use llm_engine::tool::{ Tool, ToolDefinition, ToolError, ToolExecutionContext, ToolMeta, ToolOrigin, ToolOutput, }; use manifest::McpConfig; diff --git a/crates/pod/src/feature/plugin.rs b/crates/pod/src/feature/plugin.rs index 8cf585f0..fe6ca886 100644 --- a/crates/pod/src/feature/plugin.rs +++ b/crates/pod/src/feature/plugin.rs @@ -20,7 +20,7 @@ use std::time::{Duration, Instant}; use async_trait::async_trait; use futures_util::{SinkExt, StreamExt}; -use llm_worker::tool::{ +use llm_engine::tool::{ Tool, ToolDefinition, ToolError, ToolExecutionContext, ToolMeta, ToolOrigin, ToolOutput, }; use manifest::plugin::{ diff --git a/crates/pod/src/fs_view.rs b/crates/pod/src/fs_view.rs index 583f3fc5..ebcf195d 100644 --- a/crates/pod/src/fs_view.rs +++ b/crates/pod/src/fs_view.rs @@ -12,7 +12,7 @@ use std::path::{Path, PathBuf}; -use llm_worker::Item; +use llm_engine::Item; use manifest::Scope; use tools::scoped_fs::first_symlink; use tools::{ScopedFs, ToolsError}; @@ -369,7 +369,7 @@ fn split_prefix(prefix: &str, cwd: &Path) -> (PathBuf, String, bool) { #[cfg(test)] mod tests { use super::*; - use llm_worker::ContentPart; + use llm_engine::ContentPart; use manifest::{Permission, Scope, ScopeConfig, ScopeRule}; use tempfile::TempDir; diff --git a/crates/pod/src/hook.rs b/crates/pod/src/hook.rs index 43649656..3f3c4be4 100644 --- a/crates/pod/src/hook.rs +++ b/crates/pod/src/hook.rs @@ -1,15 +1,15 @@ //! Pod-layer hook infrastructure //! //! Hooks are the **public** orchestration extension point. They receive -//! event-specific context values about each event in the Worker execution loop +//! event-specific context values about each event in the Engine execution loop //! and return a safe public control-flow action. Contexts may carry narrow //! host-created handles for approved side effects; hook return values remain //! flow-control decisions only. //! -//! Hooks intentionally cannot mutate the Worker's context, history, tool +//! Hooks intentionally cannot mutate the Engine's context, history, tool //! call, or tool result. Internal mechanisms that need such access (e.g. //! compaction, notification injection, output truncation) implement -//! `llm_worker::Interceptor` directly inside Pod, never via this trait. +//! `llm_engine::Interceptor` directly inside Pod, never via this trait. //! //! This separation lets Hooks be exposed safely to user-facing //! extension surfaces (scripting, plugins) in the future without @@ -19,10 +19,10 @@ use std::ops::Deref; use std::sync::{Arc, Mutex}; use async_trait::async_trait; -use llm_worker::interceptor::{ +use llm_engine::interceptor::{ PostToolAction, PreRequestAction, PreToolAction, PromptAction, TurnEndAction, }; -use llm_worker::tool::{ToolOutput, ToolResult}; +use llm_engine::tool::{ToolOutput, ToolResult}; use serde_json::Value; use session_store::{SystemItem, SystemReminder}; @@ -163,7 +163,7 @@ impl From for TurnEndAction { /// event-specific context. The handle queues typed requests; the host drains the /// queue, commits each entry through `LogEntry::SystemItem`, and only then makes /// the matching system message visible to the model. It deliberately exposes no -/// raw `llm_worker::Item`, history writer, event sender, `Pod`, `Worker`, or +/// raw `llm_engine::Item`, history writer, event sender, `Pod`, `Engine`, or /// notification buffer. pub struct SystemItemAppendHandle { pending: Arc>>, @@ -202,7 +202,7 @@ pub struct PromptSubmitInfo { /// Summary information included in `PreLlmRequest` contexts. pub struct PreRequestInfo { - /// Number of items currently in the Worker context. + /// Number of items currently in the Engine context. pub item_count: usize, /// Most recently observed `input_tokens` from the LLM provider. /// `None` when the Pod has no compaction state attached, or when diff --git a/crates/pod/src/interrupt_prep.rs b/crates/pod/src/interrupt_prep.rs index 2c240edc..976c4818 100644 --- a/crates/pod/src/interrupt_prep.rs +++ b/crates/pod/src/interrupt_prep.rs @@ -13,7 +13,7 @@ #[cfg(test)] use crate::prompt::catalog::PromptCatalog; -use llm_worker::Item; +use llm_engine::Item; /// Build synthetic `Item::ToolResult` items for every unanswered /// `Item::ToolCall` in `history`, preserving order. diff --git a/crates/pod/src/ipc/alerter.rs b/crates/pod/src/ipc/alerter.rs index 390e3158..82883698 100644 --- a/crates/pod/src/ipc/alerter.rs +++ b/crates/pod/src/ipc/alerter.rs @@ -137,7 +137,7 @@ mod tests { let alerter = Alerter::new(tx); for i in 0..(MAX_BUFFERED_ALERTS + 50) { - alerter.alert(AlertLevel::Warn, AlertSource::Worker, format!("msg-{i}")); + alerter.alert(AlertLevel::Warn, AlertSource::Engine, format!("msg-{i}")); } let (snapshot, _rx) = alerter.subscribe_with_snapshot(); @@ -153,9 +153,9 @@ mod tests { let (tx, _keep) = broadcast::channel::(8); let alerter = Alerter::new(tx); - alerter.alert(AlertLevel::Warn, AlertSource::Worker, "historic".into()); + alerter.alert(AlertLevel::Warn, AlertSource::Engine, "historic".into()); let (snapshot, mut rx) = alerter.subscribe_with_snapshot(); - alerter.alert(AlertLevel::Error, AlertSource::Worker, "live".into()); + alerter.alert(AlertLevel::Error, AlertSource::Engine, "live".into()); assert_eq!(snapshot.len(), 1); assert_eq!(snapshot[0].message, "historic"); diff --git a/crates/pod/src/ipc/interceptor.rs b/crates/pod/src/ipc/interceptor.rs index d8a296a3..e06ee635 100644 --- a/crates/pod/src/ipc/interceptor.rs +++ b/crates/pod/src/ipc/interceptor.rs @@ -12,13 +12,13 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use async_trait::async_trait; -use llm_worker::Item; -use llm_worker::UsageRecord; -use llm_worker::interceptor::{ +use llm_engine::Item; +use llm_engine::UsageRecord; +use llm_engine::interceptor::{ Interceptor, PostToolAction, PreRequestAction, PreToolAction, PromptAction, ToolCallInfo, ToolResultInfo, TurnEndAction, }; -use llm_worker::tool::ToolOutput; +use llm_engine::tool::ToolOutput; use tracing::info; use tracing::warn; @@ -35,7 +35,7 @@ use crate::hook::{ use crate::ipc::notify_buffer::{NotifyBuffer, build_system_item}; use crate::pod::SystemItemCommitter; use crate::prompt::catalog::PromptCatalog; -use llm_worker::token_counter::total_tokens; +use llm_engine::token_counter::total_tokens; /// Maximum number of bytes copied into `TurnEndInfo::final_text_preview`. const FINAL_TEXT_PREVIEW_LIMIT: usize = 512; @@ -53,7 +53,7 @@ pub(crate) struct PodInterceptor { usage_tracker: Option>, /// Pending-notification buffer drained into `worker.history` /// via [`Self::pending_history_appends`] just before the next LLM - /// request. The Worker `extend`s these into its persistent history + /// request. The Engine `extend`s these into its persistent history /// so the LLM has a visible trigger for any reaction it commits. pending_notifies: NotifyBuffer, /// Submit-scoped stash of resolver-produced typed system items. @@ -495,14 +495,14 @@ mod tests { .expect("task tool definition"); let (meta, tool) = def(); ToolCallInfo { - call: llm_worker::tool::ToolCall { + call: llm_engine::tool::ToolCall { id: "call-id".into(), name: name.into(), input, }, meta, tool, - context: llm_worker::tool::ToolExecutionContext::new("call-id", "test-batch", 0), + context: llm_engine::tool::ToolExecutionContext::new("call-id", "test-batch", 0), } } @@ -590,7 +590,7 @@ mod tests { let history = usage_handle_with(ctx_items.len(), 50); let usage_tracker = Arc::new(UsageTracker::new()); usage_tracker.note_request(ctx_items.len()); - usage_tracker.record_usage(&llm_worker::event::UsageEvent { + usage_tracker.record_usage(&llm_engine::event::UsageEvent { input_tokens: Some(150), output_tokens: Some(0), total_tokens: Some(150), @@ -656,7 +656,7 @@ mod tests { cache_write_tokens: 0, output_tokens: 0, }; - let prefix = llm_worker::token_counter::prefix_bytes(&ctx_items); + let prefix = llm_engine::token_counter::prefix_bytes(&ctx_items); let delta_bytes = prefix[2].saturating_sub(prefix[1]); let old_projection = 11_124 + (delta_bytes as u128 * 11_124_u128 / prefix[1] as u128) as u64; @@ -767,7 +767,7 @@ mod tests { assert!(matches!( &items[0], Item::Message { - role: llm_worker::Role::System, + role: llm_engine::Role::System, .. } )); @@ -912,7 +912,7 @@ mod tests { let info = task_tool_call_info("TaskList", serde_json::json!({})); let mut result_info = ToolResultInfo { call: info.call, - result: llm_worker::tool::ToolResult::from_output( + result: llm_engine::tool::ToolResult::from_output( "call-id", ToolOutput { summary: "ok".into(), @@ -1001,7 +1001,7 @@ mod tests { let mut ctx = ctx_items.clone(); let action = interceptor.pre_llm_request(&mut ctx).await; assert!(matches!(action, PreRequestAction::Continue)); - usage_tracker.record_usage(&llm_worker::event::UsageEvent { + usage_tracker.record_usage(&llm_engine::event::UsageEvent { input_tokens: Some(10), output_tokens: Some(0), total_tokens: Some(10), @@ -1017,7 +1017,7 @@ mod tests { other => panic!("expected reminder append, got {other:?}"), }; assert_eq!(appended_len, 1); - usage_tracker.record_usage(&llm_worker::event::UsageEvent { + usage_tracker.record_usage(&llm_engine::event::UsageEvent { input_tokens: Some(11), output_tokens: Some(0), total_tokens: Some(11), diff --git a/crates/pod/src/ipc/notify_buffer.rs b/crates/pod/src/ipc/notify_buffer.rs index d2ee22e5..c7fb4e0a 100644 --- a/crates/pod/src/ipc/notify_buffer.rs +++ b/crates/pod/src/ipc/notify_buffer.rs @@ -2,7 +2,7 @@ //! //! Entries are queued here by the Controller (on receipt of the //! corresponding IPC method) and drained by -//! `PodInterceptor::pending_history_appends`, which the Worker calls +//! `PodInterceptor::pending_history_appends`, which the Engine calls //! at the head of each turn loop iteration. The drain renders each //! pending entry into a typed `SystemItem` (with the `notify_wrapper` //! prompt applied), commits a `LogEntry::SystemItem` per entry through diff --git a/crates/pod/src/permission.rs b/crates/pod/src/permission.rs index d4418061..1821ac13 100644 --- a/crates/pod/src/permission.rs +++ b/crates/pod/src/permission.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use llm_worker::llm_client::client::LlmClient; +use llm_engine::llm_client::client::LlmClient; use manifest::{ToolPermissionAction, ToolPermissionConfig}; use serde_json::Value; use session_store::Store; diff --git a/crates/pod/src/pod.rs b/crates/pod/src/pod.rs index 5994580d..21695724 100644 --- a/crates/pod/src/pod.rs +++ b/crates/pod/src/pod.rs @@ -4,12 +4,12 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use arc_swap::ArcSwap; -use llm_worker::Item; -use llm_worker::llm_client::RequestConfig; -use llm_worker::llm_client::client::LlmClient; -use llm_worker::llm_client::types::Role; -use llm_worker::state::Mutable; -use llm_worker::{ToolOutputLimits, UsageRecord, Worker, WorkerError, WorkerResult}; +use llm_engine::Item; +use llm_engine::llm_client::RequestConfig; +use llm_engine::llm_client::client::LlmClient; +use llm_engine::llm_client::types::Role; +use llm_engine::state::Mutable; +use llm_engine::{Engine, EngineError, EngineResult, ToolOutputLimits, UsageRecord}; use pod_store::{ PodActiveSegmentRef, PodMetadata, PodMetadataStore, PodReclaimedChild, PodSpawnedChild, PodSpawnedScopeRule, PodStoreError, @@ -233,12 +233,12 @@ where /// An independent agent execution unit. /// -/// Holds a [`Worker`] directly and persists session state via +/// Holds a [`Engine`] directly and persists session state via /// `session-store` functions after each turn. pub struct Pod { manifest: PodManifest, /// Always `Some` outside of `run()`/`resume()`. - worker: Option>, + engine: Option>, store: St, /// Optional write-through hook for name-keyed Pod metadata. Production /// constructors install this from the same FsStore that owns the session @@ -269,7 +269,7 @@ pub struct Pod { /// Captures `(history_len, UsageEvent)` pairs during a run; drained /// in `persist_turn` and persisted as `LogEntry::LlmUsage` entries. usage_tracker: Arc, - /// Sync-side buffer for `Metric` values queued from inside Worker + /// Sync-side buffer for `Metric` values queued from inside Engine /// callbacks (currently the prune observer). Drained in `persist_turn` /// and written via `session_metrics::record_metric` alongside /// `LogEntry::LlmUsage`. Always present after construction. @@ -279,7 +279,7 @@ pub struct Pod { /// Read by token-accounting APIs (`Pod::total_tokens`, etc.). /// /// Wrapped in `Arc` so that callbacks injected into the - /// Worker (e.g. the savings estimator used by the prune projection) + /// Engine (e.g. the savings estimator used by the prune projection) /// can share the same view via [`Pod::usage_history_handle`]. usage_history: Arc>>, /// Pod-lifetime file-operation tracker from the builtin `tools` @@ -402,7 +402,7 @@ pub struct Pod { /// on disk. sink: SegmentLogSink, /// `true` once `wire_history_persistence` has installed the - /// `Worker::on_history_append` callback that commits each appended + /// `Engine::on_history_append` callback that commits each appended /// item as a singular `LogEntry::AssistantItem` / `ToolResult` /// directly through the writer. Tests that drive `Pod::new` without /// going through the controller leave this `false`; `persist_turn` @@ -436,12 +436,12 @@ impl Pod { // methods using `worker.client()` as fallback when no override // model is configured. system_prompt / request_config / cache_key // are unused on this path, so we deliberately skip copying them. - let source_worker = self.worker.as_ref().expect("worker present"); - let mut worker = Worker::new(source_worker.client().clone()); + let source_worker = self.engine.as_ref().expect("worker present"); + let mut worker = Engine::new(source_worker.client().clone()); worker.set_history(source_worker.history().to_vec()); Self { manifest: self.manifest.clone(), - worker: Some(worker), + engine: Some(worker), store: self.store.clone(), pod_metadata_writer: None, segment_state: self.segment_state.clone(), @@ -513,7 +513,7 @@ impl Pod { self.in_flight = Some(in_flight); } - /// Wire `Worker::on_history_append` to commit each appended item + /// Wire `Engine::on_history_append` to commit each appended item /// directly as a singular `LogEntry::AssistantItem` / `ToolResult` /// through the writer. The controller calls this once per spawned /// Pod after the worker is built; tests that drive `Pod::new` may @@ -528,14 +528,14 @@ impl Pod { /// callback would otherwise double-write them. pub fn wire_history_persistence(&mut self) { let writer = self.log_writer_handle(); - self.worker_mut().on_history_append(move |item| { + self.engine_mut().on_history_append(move |item| { if item.is_user_message() { return; } if matches!( item, Item::Message { - role: llm_worker::Role::System, + role: llm_engine::Role::System, .. } ) { @@ -548,7 +548,7 @@ impl Pod { }); if self.manifest.session.record_event_trace { let writer = self.log_writer_handle(); - self.worker_mut() + self.engine_mut() .on_stream_event(move |turn, llm_call, event| { let entry = session_store::TraceEntry { ts: segment_log::now_millis(), @@ -563,7 +563,7 @@ impl Pod { } }); let writer = self.log_writer_handle(); - self.worker_mut() + self.engine_mut() .on_lifecycle_trace(move |turn, llm_call, label, data| { let entry = session_store::TraceEntry { ts: segment_log::now_millis(), @@ -604,7 +604,7 @@ impl Pod { } impl Pod { - /// Create a new Pod from a pre-built Worker and store. + /// Create a new Pod from a pre-built Engine and store. /// /// Callers must pre-resolve `cwd` (absolute) and build a [`Scope`] /// — typically via [`Scope::from_config`] when coming from a @@ -616,7 +616,7 @@ impl Pod { /// should parse it themselves and call [`set_system_prompt_template`]. pub async fn new( manifest: PodManifest, - worker: Worker, + worker: Engine, store: St, cwd: PathBuf, scope: Scope, @@ -631,7 +631,7 @@ impl Pod { DelegationScope::from_config(&manifest.delegation_scope).map_err(PodError::Scope)?; let mut pod = Self { manifest, - worker: Some(worker), + engine: Some(worker), store, pod_metadata_writer: None, segment_state: SegmentState::new(session_id, segment_id, 0), @@ -825,17 +825,17 @@ impl Pod { self.sink.clone() } - /// Direct access to the underlying Worker. - pub fn worker(&self) -> &Worker { - self.worker.as_ref().expect("worker taken during run") + /// Direct access to the underlying Engine. + pub fn engine(&self) -> &Engine { + self.engine.as_ref().expect("worker taken during run") } - /// Mutable access to the underlying Worker. + /// Mutable access to the underlying Engine. /// /// Use this to register tools, hooks, or subscribers before calling /// [`run`](Self::run). - pub fn worker_mut(&mut self) -> &mut Worker { - self.worker.as_mut().expect("worker taken during run") + pub fn engine_mut(&mut self) -> &mut Engine { + self.engine.as_mut().expect("worker taken during run") } /// Install enabled feature modules into the Pod host surfaces. @@ -843,7 +843,7 @@ impl Pod { &mut self, registry: FeatureRegistryBuilder, ) -> FeatureRegistryInstallReport { - let worker = self.worker.as_mut().expect("worker taken during run"); + let worker = self.engine.as_mut().expect("worker taken during run"); let active_workflow_committer = self.log_writer.clone().map(|writer| { Arc::new(move |entry| writer.commit_log_entry(entry)) as active_workflow::LogEntryCommitter @@ -852,7 +852,7 @@ impl Pod { self.active_workflows.clone(), active_workflow_committer, )); - let report = registry.install_into_worker(worker, &mut self.hook_builder); + let report = registry.install_into_engine(worker, &mut self.hook_builder); report } @@ -920,10 +920,10 @@ impl Pod { .restore_from_history_and_extensions(&state.history, &state.extensions); let mut history = state.history; active_workflow::strip_rehydration_messages(&mut history); - self.worker_mut().set_history(history); - self.worker_mut().set_request_config(state.config); - self.worker_mut().set_turn_count(state.turn_count); - self.worker_mut() + self.engine_mut().set_history(history); + self.engine_mut().set_request_config(state.config); + self.engine_mut().set_turn_count(state.turn_count); + self.engine_mut() .set_last_run_interrupted(state.last_run_interrupted); self.user_segments = state.user_segments; *self.usage_history.lock().expect("usage_history poisoned") = state.usage_history; @@ -980,9 +980,9 @@ impl Pod { self.write_pod_metadata_pending() } - /// Current history items held by the underlying Worker. + /// Current history items held by the underlying Engine. pub fn history(&self) -> &[Item] { - self.worker().history() + self.engine().history() } /// Snapshot of the cumulative LLM Usage measurement timeline. @@ -990,7 +990,7 @@ impl Pod { /// One entry per LLM call. Restored on `restore` and appended in /// `persist_turn`. Used by token-accounting APIs in [`token_counter`]. /// Returns a clone since the underlying vector is shared with hooks - /// running on the Worker. + /// running on the Engine. pub fn usage_history(&self) -> Vec { self.usage_history .lock() @@ -1033,7 +1033,7 @@ impl Pod { /// Shared handle to the cumulative Usage history. /// /// Callbacks that need live access to the latest measurements (e.g. - /// the savings estimator that `attach_prune` installs on the Worker) + /// the savings estimator that `attach_prune` installs on the Engine) /// clone this `Arc` and read it at request time. The handle outlives /// any individual run. /// @@ -1057,7 +1057,7 @@ impl Pod { /// Handle to the synchronous `MetricsTracker` buffer. /// - /// Worker callbacks (e.g. the prune observer) clone this `Arc` and + /// Engine callbacks (e.g. the prune observer) clone this `Arc` and /// `.push(metric)` into it; Pod drains it in `persist_turn` and /// writes each metric via `session_metrics::record_metric`. pub(crate) fn metrics_tracker_handle( @@ -1068,7 +1068,7 @@ impl Pod { /// Attach the session-scoped file-operation tracker from the builtin /// `tools` crate. Called by the Controller immediately after it - /// registers the builtin tools on the Worker. Overwrites any + /// registers the builtin tools on the Engine. Overwrites any /// previously attached tracker. pub fn attach_tracker(&mut self, tracker: tools::Tracker) { self.tracker = Some(tracker); @@ -1227,7 +1227,7 @@ impl Pod { self.hook_builder.add_on_abort(hook); } - /// Install the hook-based interceptor on the Worker if not already done. + /// Install the hook-based interceptor on the Engine if not already done. /// /// When either compaction threshold (`threshold` or /// `request_threshold`) is configured in the manifest, allocates @@ -1246,7 +1246,7 @@ impl Pod { .unwrap_or((None, None, manifest::defaults::COMPACT_RETAINED_TOKENS)); let tracker_for_usage = self.usage_tracker.clone(); - self.worker_mut().on_usage(move |event| { + self.engine_mut().on_usage(move |event| { tracker_for_usage.record_usage(event); }); @@ -1285,7 +1285,7 @@ impl Pod { self.active_workflows.clone(), ) .with_usage_tracker(self.usage_tracker.clone()); - self.worker_mut().set_interceptor(interceptor); + self.engine_mut().set_interceptor(interceptor); self.interceptor_installed = true; } } @@ -1293,7 +1293,7 @@ impl Pod { /// Render the manifest-supplied instruction template exactly once, /// just before the first LLM turn, append the fixed trailing /// section (scope summary + optional AGENTS.md), and hand the - /// resulting string to the Worker via `set_system_prompt`. + /// resulting string to the Engine via `set_system_prompt`. /// Subsequent invocations are no-ops: the template field is /// consumed with `Option::take()`, so the materialised value /// persists across all later turns and compaction. @@ -1303,10 +1303,10 @@ impl Pod { }; let alerter = self.alerter.clone(); let tool_names: Vec = { - let worker = self.worker.as_mut().expect("worker present"); + let worker = self.engine.as_mut().expect("worker present"); // Materialise any pending tool factories so the template sees the // full list of tool names. Redundant with the flush inside - // `Worker::lock()`; safe because `flush_pending` is idempotent. + // `Engine::lock()`; safe because `flush_pending` is idempotent. worker.tool_server_handle().flush_pending(); worker .tool_server_handle() @@ -1386,7 +1386,7 @@ impl Pod { let rendered = template .render(&ctx) .map_err(|source| PodError::SystemPromptRender { source })?; - self.worker + self.engine .as_mut() .expect("worker present") .set_system_prompt(rendered); @@ -1461,30 +1461,30 @@ impl Pod { .expect("usage_history poisoned") .len(); EmptyTurnRollbackSnapshot { - history_len: self.worker().history().len(), + history_len: self.engine().history().len(), user_segments_len: self.user_segments.len(), entries_written: self.segment_state.entries_written(), sink_len: self.sink.len(), pending_attachments, usage_history_len, ai_activity_count: self.ai_activity_counter.load(Ordering::SeqCst), - last_run_interrupted: self.worker().last_run_interrupted(), + last_run_interrupted: self.engine().last_run_interrupted(), active_workflows: self.active_workflows.snapshot(), } } fn should_rollback_empty_turn( &self, - result: &Result, + result: &Result, snapshot: &EmptyTurnRollbackSnapshot, ) -> bool { - if !matches!(result, Err(WorkerError::Cancelled)) { + if !matches!(result, Err(EngineError::Cancelled)) { return false; } if self.ai_activity_counter.load(Ordering::SeqCst) != snapshot.ai_activity_count { return false; } - !self.worker().history()[snapshot.history_len..] + !self.engine().history()[snapshot.history_len..] .iter() .any(is_ai_materialized_item) } @@ -1493,8 +1493,8 @@ impl Pod { &mut self, snapshot: EmptyTurnRollbackSnapshot, ) -> Result<(), StoreError> { - self.worker_mut().truncate_history(snapshot.history_len); - self.worker_mut() + self.engine_mut().truncate_history(snapshot.history_len); + self.engine_mut() .set_last_run_interrupted(snapshot.last_run_interrupted); self.user_segments.truncate(snapshot.user_segments_len); *self @@ -1523,12 +1523,12 @@ impl Pod { /// /// `input` is a typed segment list (see [`protocol::Segment`]). The /// Pod flattens it into a single user-message string for the - /// underlying Worker, expanding paste content inline, resolving file refs + /// underlying Engine, expanding paste content inline, resolving file refs /// into adjacent attachments where possible, and surfacing alerts for /// unresolved refs / unsupported segment kinds. /// /// If the between-turns compaction threshold is exceeded mid-run, - /// the Worker is aborted, history is compacted, and execution resumes + /// the Engine is aborted, history is compacted, and execution resumes /// automatically. pub async fn run(&mut self, input: Vec) -> Result { // Validate workflow invocations up front so an invalid slug @@ -1547,7 +1547,7 @@ impl Pod { // `last_run_interrupted` flag; `Pod::resume` reuses the prior // context via a different entry point and never triggers this // path. - if self.worker.as_ref().unwrap().last_run_interrupted() { + if self.engine.as_ref().unwrap().last_run_interrupted() { self.apply_interrupt_prep()?; } @@ -1575,7 +1575,7 @@ impl Pod { // workflow invocations to system messages stashed for the // PodInterceptor to attach right after the user message. File and // Knowledge failures are non-fatal alerts; explicit workflow invocation - // failures abort before the Worker sees the turn. + // failures abort before the Engine sees the turn. let mut attachments = self.resolve_file_refs(&input); attachments.extend(self.resolve_knowledge_refs(&input)); attachments.extend(self.resolve_workflow_invocations(&input)?); @@ -1594,13 +1594,13 @@ impl Pod { .expect("pending_attachments poisoned") = attachments; } - let history_before = self.worker.as_ref().unwrap().history().len(); + let history_before = self.engine.as_ref().unwrap().history().len(); // lock → run → unlock - let worker = self.worker.take().expect("worker taken during run"); + let worker = self.engine.take().expect("worker taken during run"); let mut locked = worker.lock(); let result = locked.run(flattened).await; - self.worker = Some(locked.unlock()); + self.engine = Some(locked.unlock()); if self.should_rollback_empty_turn(&result, &rollback_snapshot) { self.rollback_empty_turn(rollback_snapshot)?; @@ -1844,11 +1844,11 @@ impl Pod { .map_err(PodError::from)?; let closures = crate::interrupt_prep::orphan_tool_result_closures( - self.worker().history(), + self.engine().history(), &tool_result_summary, ); if !closures.is_empty() { - self.worker_mut().append_history(closures); + self.engine_mut().append_history(closures); } self.commit_entry(LogEntry::SystemItem { ts: segment_log::now_millis(), @@ -1856,8 +1856,8 @@ impl Pod { body: system_note.clone(), }, })?; - self.worker_mut() - .append_history(std::iter::once(llm_worker::Item::system_message( + self.engine_mut() + .append_history(std::iter::once(llm_engine::Item::system_message( system_note, ))); Ok(()) @@ -1871,12 +1871,12 @@ impl Pod { /// The explicit `PausedTurnAbandoned` marker preserves durable lifecycle /// semantics without claiming another `run` / `resume` completed. pub fn cancel_paused_turn(&mut self) -> Result<(), PodError> { - if !self.worker().last_run_interrupted() { + if !self.engine().last_run_interrupted() { return Ok(()); } self.apply_interrupt_prep()?; - self.worker_mut().set_last_run_interrupted(false); + self.engine_mut().set_last_run_interrupted(false); self.commit_entry(LogEntry::PausedTurnAbandoned { ts: segment_log::now_millis(), })?; @@ -1920,7 +1920,7 @@ impl Pod { .unwrap_or_default() } - /// Flatten a typed segment list into the single string the Worker + /// Flatten a typed segment list into the single string the Engine /// receives as the user message, and emit user-facing alerts for /// segments that fall through to placeholder (knowledge / workflow /// refs without a resolver, or unknown variants from a newer client). @@ -1964,7 +1964,7 @@ impl Pod { /// history. The `PodInterceptor::pre_llm_request` drains the /// pending-notification buffer and injects each entry as an /// `Item::system_message` into the per-request context, then the - /// Worker's resume path issues the LLM request without a new + /// Engine's resume path issues the LLM request without a new /// user turn. pub async fn run_for_notification( &mut self, @@ -1990,12 +1990,12 @@ impl Pod { trigger: kind, })?; - let history_before = self.worker.as_ref().unwrap().history().len(); + let history_before = self.engine.as_ref().unwrap().history().len(); - let worker = self.worker.take().expect("worker taken during run"); + let worker = self.engine.take().expect("worker taken during run"); let mut locked = worker.lock(); let result = locked.resume().await; - self.worker = Some(locked.unlock()); + self.engine = Some(locked.unlock()); self.handle_worker_result(result, history_before).await } @@ -2004,13 +2004,13 @@ impl Pod { pub async fn resume(&mut self) -> Result { self.prepare_for_run().await?; - let history_before = self.worker.as_ref().unwrap().history().len(); + let history_before = self.engine.as_ref().unwrap().history().len(); // lock → resume → unlock - let worker = self.worker.take().expect("worker taken during run"); + let worker = self.engine.take().expect("worker taken during run"); let mut locked = worker.lock(); let result = locked.resume().await; - self.worker = Some(locked.unlock()); + self.engine = Some(locked.unlock()); self.handle_worker_result(result, history_before).await } @@ -2025,7 +2025,7 @@ impl Pod { /// calls fall through to entry-count comparison, which auto-forks /// when another writer has appended behind our back. fn ensure_segment_head(&mut self) -> Result<(), PodError> { - let w = self.worker.as_ref().unwrap(); + let w = self.engine.as_ref().unwrap(); let loc = self.segment_state.location(); let entries_written = self.segment_state.entries_written(); if entries_written == 0 { @@ -2090,7 +2090,7 @@ impl Pod { Ok(()) } - /// Handle Worker result: always persist the turn first, then if + /// Handle Engine result: always persist the turn first, then if /// `Yielded`, perform compaction and resume. /// /// Persisting before compaction ensures that if compact fails, the @@ -2098,12 +2098,12 @@ impl Pod { /// `Yielded`), so restore remains consistent. async fn handle_worker_result( &mut self, - result: Result, + result: Result, history_before: usize, ) -> Result { self.persist_turn(history_before, &result).await?; - if matches!(result, Ok(WorkerResult::Yielded)) { + if matches!(result, Ok(EngineResult::Yielded)) { return self.do_compact_and_resume().await; } @@ -2112,7 +2112,7 @@ impl Pod { state.set_just_compacted(false); } } - result.map(PodRunResult::from).map_err(PodError::Worker) + result.map(PodRunResult::from).map_err(PodError::Engine) } /// Perform compaction after a `compact_needed` abort and resume execution. @@ -2218,7 +2218,7 @@ impl Pod { /// Run an explicit user-requested compaction between turns. /// /// The controller only calls this while Idle. Paused turns keep their - /// interrupted Worker state intact and are intentionally rejected before + /// interrupted Engine state intact and are intentionally rejected before /// this method is reached. pub async fn manual_compact(&mut self) -> Result { if self.manifest.compaction.is_none() { @@ -2294,7 +2294,7 @@ impl Pod { async fn persist_turn( &mut self, history_before: usize, - result: &Result, + result: &Result, ) -> Result<(), StoreError> { // Per-item commits for AssistantItem / ToolResult / SystemItem // entries are expected to have landed synchronously: the @@ -2310,7 +2310,7 @@ impl Pod { // slice from `history_before` inline so the test's // `restore`-style assertions still see entries on disk. if !self.history_persistence_wired { - let new_items: Vec = self.worker.as_ref().unwrap().history()[history_before..] + let new_items: Vec = self.engine.as_ref().unwrap().history()[history_before..] .iter() .cloned() .collect(); @@ -2322,7 +2322,7 @@ impl Pod { if matches!( item, Item::Message { - role: llm_worker::Role::System, + role: llm_engine::Role::System, .. } ) { @@ -2333,7 +2333,7 @@ impl Pod { } } - let turn_count = self.worker.as_ref().unwrap().turn_count(); + let turn_count = self.engine.as_ref().unwrap().turn_count(); self.commit_entry(LogEntry::TurnEnd { ts: segment_log::now_millis(), turn_count, @@ -2392,7 +2392,7 @@ impl Pod { .push(record); } - let interrupted = self.worker.as_ref().unwrap().last_run_interrupted(); + let interrupted = self.engine.as_ref().unwrap().last_run_interrupted(); match result { Ok(r) => { self.commit_entry(LogEntry::RunCompleted { @@ -2414,10 +2414,10 @@ impl Pod { } /// Compact the current session by summarising history via a - /// disposable Worker, then replacing history with + /// disposable Engine, then replacing history with /// `[summary, ...recent_turns]` and creating a new session. /// - /// The summary Worker uses: + /// The summary Engine uses: /// - `compaction.model` from the manifest if configured, or /// - a clone of the main LlmClient via `clone_boxed()`. /// @@ -2435,7 +2435,7 @@ impl Pod { // within `retained_tokens`. Item-granular, turn boundaries ignored. let cut = self.split_for_retained(retained_tokens); - let worker = self.worker.as_ref().expect("worker taken during run"); + let worker = self.engine.as_ref().expect("worker taken during run"); let history = worker.history(); let retain_from = cut.index.min(history.len()); let mut retained_items = history[retain_from..].to_vec(); @@ -2537,7 +2537,7 @@ impl Pod { ); } - // Worker-side state collected by the compact worker's tool calls. + // Engine-side state collected by the compact worker's tool calls. let ctx = Arc::new(std::sync::Mutex::new(CompactWorkerContext::with_budget( auto_read_budget, ))); @@ -2553,7 +2553,7 @@ impl Pod { .prompts .compact_system() .map_err(PodError::PromptCatalog)?; - let mut summary_worker = Worker::new(summary_client).system_prompt(summary_system_prompt); + let mut summary_worker = Engine::new(summary_client).system_prompt(summary_system_prompt); summary_worker.set_cache_key(Some(self.segment_id().to_string())); // Occupancy-based input-token meter + interceptor. The tracker pairs @@ -2594,8 +2594,8 @@ impl Pod { let out = summary_worker .run(summary_input.text) .await - .map_err(PodError::Worker)?; - let mut locked_worker = out.worker; + .map_err(PodError::Engine)?; + let mut locked_engine = out.engine; // Guard: nudge the worker once more if the expected outputs // (summary, and any auto-read nominations when default refs @@ -2624,7 +2624,7 @@ impl Pod { } }; if let Some(prompt) = nudge { - let _ = locked_worker.run(prompt).await.map_err(PodError::Worker)?; + let _ = locked_engine.run(prompt).await.map_err(PodError::Engine)?; } let mut final_ctx = ctx.lock().expect("compact ctx poisoned").clone(); @@ -2639,7 +2639,7 @@ impl Pod { {summary_max_tokens}). Rewrite it now with `write_summary`, preserving the \ same five sections but making it concise. Target ≈{summary_target_tokens} tokens." ); - let _ = locked_worker.run(prompt).await.map_err(PodError::Worker)?; + let _ = locked_engine.run(prompt).await.map_err(PodError::Engine)?; final_ctx = ctx.lock().expect("compact ctx poisoned").clone(); summary_text = final_ctx .summary @@ -2728,7 +2728,7 @@ impl Pod { self.task_feature.snapshot_overview(), task_snapshot_text.clone(), )); - let result_estimate = llm_worker::token_counter::total_tokens(&new_history, &[]); + let result_estimate = llm_engine::token_counter::total_tokens(&new_history, &[]); if result_context_max_tokens > 0 && result_estimate.tokens > result_context_max_tokens { return Err(PodError::CompactResultContextTooLarge { tokens: result_estimate.tokens, @@ -2744,8 +2744,8 @@ impl Pod { // { compacted_from }` and reset their view. let new_segment_id = session_store::new_segment_id(); let old_loc = self.segment_state.location(); - let source_turn_count = self.worker.as_ref().unwrap().turn_count(); - let w = self.worker.as_ref().unwrap(); + let source_turn_count = self.engine.as_ref().unwrap().turn_count(); + let w = self.engine.as_ref().unwrap(); let entry = LogEntry::SegmentStart { ts: segment_log::now_millis(), session_id: old_loc.session_id, @@ -2798,13 +2798,13 @@ impl Pod { self.user_segments.drain(..drop_n); } - self.worker.as_mut().unwrap().set_history(new_history); + self.engine.as_mut().unwrap().set_history(new_history); // Compaction-introduced system messages are part of the new // SegmentStart's history (broadcast above) — clients derive // their blocks from `SegmentStart.history`. No per-item // broadcast is required. let _ = &compact_introduced_system_messages; - let worker = self.worker.as_mut().unwrap(); + let worker = self.engine.as_mut().unwrap(); // Anchor the prompt cache at the summary item so that Anthropic // can place a durable `cache_control` breakpoint there — our // compact layout guarantees history[0] is the summary. @@ -2833,7 +2833,7 @@ impl Pod { Ok(new_segment_id) } - /// Build the LlmClient for the compactor Worker. + /// Build the LlmClient for the compactor Engine. /// /// Uses `compaction.model` from manifest if set, otherwise clones /// the main client. @@ -2844,11 +2844,11 @@ impl Pod { return Ok(client); } } - let worker = self.worker.as_ref().expect("worker taken during run"); + let worker = self.engine.as_ref().expect("worker taken during run"); Ok(worker.client().clone_boxed()) } - /// Build the LlmClient for the extract (memory.extract) Worker. + /// Build the LlmClient for the extract (memory.extract) Engine. /// /// Uses `memory.extract_model` from manifest if set, otherwise clones /// the main client. @@ -2860,7 +2860,7 @@ impl Pod { let client = provider::build_client(m)?; return Ok(client); } - let worker = self.worker.as_ref().expect("worker taken during run"); + let worker = self.engine.as_ref().expect("worker taken during run"); Ok(worker.client().clone_boxed()) } @@ -3027,9 +3027,9 @@ impl Pod { } let current_history_len = self - .worker + .engine .as_ref() - .expect("worker present") + .expect("engine present") .history() .len(); if current_history_len <= processed_history_len { @@ -3108,7 +3108,7 @@ impl Pod { None, ); - let items_to_extract = self.worker.as_ref().expect("worker present").history() + let items_to_extract = self.engine.as_ref().expect("worker present").history() [processed_history_len..current_history_len] .to_vec(); @@ -3147,7 +3147,7 @@ impl Pod { return Err(PodError::PromptCatalog(err)); } }; - let mut extract_worker = Worker::new(client).system_prompt(extract_system_prompt); + let mut extract_worker = Engine::new(client).system_prompt(extract_system_prompt); extract_worker.set_cache_key(Some(self.segment_id().to_string())); extract_worker.set_max_turns(extract_worker_max_turns); @@ -3179,7 +3179,7 @@ impl Pod { Some(extract_audit_base), None, ); - return Err(PodError::Worker(err)); + return Err(PodError::Engine(err)); } let payload = ctx.take_payload().unwrap_or_else(|| { @@ -3271,7 +3271,7 @@ impl Pod { Ok(ExtractDecision::Completed) } - /// Build the LlmClient for the consolidation (memory.consolidation) Worker. + /// Build the LlmClient for the consolidation (memory.consolidation) Engine. /// /// Uses `memory.consolidation_model` from manifest if set, otherwise /// clones the main client. Mirrors [`build_extractor_client`]. @@ -3283,7 +3283,7 @@ impl Pod { let client = provider::build_client(m)?; return Ok(client); } - let worker = self.worker.as_ref().expect("worker taken during run"); + let worker = self.engine.as_ref().expect("worker taken during run"); Ok(worker.client().clone_boxed()) } @@ -3534,7 +3534,7 @@ impl Pod { return Err(PodError::PromptCatalog(e)); } }; - let mut worker = Worker::new(client).system_prompt(consolidation_system_prompt); + let mut worker = Engine::new(client).system_prompt(consolidation_system_prompt); worker.set_cache_key(Some(self.segment_id().to_string())); let usage_capture = Arc::new(Mutex::new(None)); @@ -3548,7 +3548,7 @@ impl Pod { // Memory tools are self-contained — they bypass ScopedFs and write // directly under the workspace via WorkspaceLayout. Resident section - // injection is a Pod-level concern; this disposable Worker is built + // injection is a Pod-level concern; this disposable Engine is built // without it by construction, in keeping with `docs/plan/memory.md` // §Consolidation のKnowledgeアクセス (agent pulls knowledge through // the search tool instead of via system-prompt residency). @@ -3616,14 +3616,14 @@ impl Pod { None, Some(base_consolidation), ); - Err(PodError::Worker(e)) + Err(PodError::Engine(e)) } } } } -fn lifecycle_status_for_worker_error(err: &WorkerError) -> memory::audit::WorkerLifecycleStatus { - if matches!(err, WorkerError::Cancelled) { +fn lifecycle_status_for_worker_error(err: &EngineError) -> memory::audit::WorkerLifecycleStatus { + if matches!(err, EngineError::Cancelled) { memory::audit::WorkerLifecycleStatus::Cancelled } else { memory::audit::WorkerLifecycleStatus::Failed @@ -3631,7 +3631,7 @@ fn lifecycle_status_for_worker_error(err: &WorkerError) -> memory::audit::Worker } fn usage_audit_from_event( - event: &llm_worker::llm_client::event::UsageEvent, + event: &llm_engine::llm_client::event::UsageEvent, ) -> memory::audit::UsageAudit { memory::audit::UsageAudit { input_tokens: event.input_tokens, @@ -3854,14 +3854,14 @@ where segment_id, )?; - let mut worker = Worker::new(common.client); + let mut worker = Engine::new(common.client); apply_worker_manifest(&mut worker, &manifest.worker); worker.set_cache_key(Some(segment_id.to_string())); let pod_metadata_writer = Some(pod_metadata_writer_for_store(&store)); let mut pod = Self { manifest, - worker: Some(worker), + engine: Some(worker), store, pod_metadata_writer, segment_state: SegmentState::new(session_id, segment_id, 0), @@ -3964,14 +3964,14 @@ where segment_id, )?; - let mut worker = Worker::new(common.client); + let mut worker = Engine::new(common.client); apply_worker_manifest(&mut worker, &manifest.worker); worker.set_cache_key(Some(segment_id.to_string())); let pod_metadata_writer = Some(pod_metadata_writer_for_store(&store)); let mut pod = Self { manifest, - worker: Some(worker), + engine: Some(worker), store, pod_metadata_writer, segment_state: SegmentState::new(session_id, segment_id, 0), @@ -4087,7 +4087,7 @@ where /// Restore a Pod from an existing session log. /// /// Uses the resolved manifest supplied by the caller, seeds a - /// fresh Worker from the source session's `RestoredState`, and + /// fresh Engine from the source session's `RestoredState`, and /// reuses the same `segment_id` so subsequent turns append to the /// source jsonl as a continuation of the same conversation. /// @@ -4171,7 +4171,7 @@ where // Build the worker and apply the manifest defaults first, then // overwrite the pieces the session log is authoritative for. - let mut worker = Worker::new(common.client); + let mut worker = Engine::new(common.client); apply_worker_manifest(&mut worker, &manifest.worker); worker.set_cache_key(Some(segment_id.to_string())); if let Some(ref prompt) = state.system_prompt { @@ -4184,7 +4184,7 @@ where let anchored_on_summary = matches!( state.history.first(), Some(Item::Message { - role: llm_worker::Role::System, + role: llm_engine::Role::System, .. }) ); @@ -4206,7 +4206,7 @@ where let mut pod = Self { manifest, - worker: Some(worker), + engine: Some(worker), store, pod_metadata_writer, segment_state: SegmentState::new(session_id, segment_id, state.entries_count), @@ -4327,12 +4327,12 @@ where } } -/// Apply worker-level manifest settings to a Worker. +/// Apply worker-level manifest settings to a Engine. /// /// Note: `system_prompt` is intentionally not applied here. It is a /// minijinja template that is parsed by `Pod::from_manifest` and /// rendered once at first turn in `ensure_system_prompt_materialized`. -pub fn apply_worker_manifest(worker: &mut Worker, wm: &WorkerManifest) { +pub fn apply_worker_manifest(worker: &mut Engine, wm: &WorkerManifest) { worker.set_request_config(request_config_from_worker_manifest(wm)); worker.set_max_turns(wm.max_turns.map(|n| n.get())); worker.set_tool_output_limits(Some(ToolOutputLimits { @@ -4415,15 +4415,15 @@ pub enum ManualCompactResult { Skipped { message: String }, } -impl From for PodRunResult { - fn from(r: WorkerResult) -> Self { +impl From for PodRunResult { + fn from(r: EngineResult) -> Self { match r { - WorkerResult::Finished => PodRunResult::Finished, - WorkerResult::Paused => PodRunResult::Paused, - WorkerResult::LimitReached => PodRunResult::LimitReached, + EngineResult::Finished => PodRunResult::Finished, + EngineResult::Paused => PodRunResult::Paused, + EngineResult::LimitReached => PodRunResult::LimitReached, // Yielded is internal to Pod: it's always caught by // handle_worker_result and never converted to PodRunResult. - WorkerResult::Yielded => unreachable!("Yielded never converts to PodRunResult"), + EngineResult::Yielded => unreachable!("Yielded never converts to PodRunResult"), } } } @@ -4644,9 +4644,9 @@ fn message_overview_entry(idx: usize, item: &Item, max_chars: usize) -> Option "User", - llm_worker::Role::Assistant => "Assistant", - llm_worker::Role::System => "System", + llm_engine::Role::User => "User", + llm_engine::Role::Assistant => "Assistant", + llm_engine::Role::System => "System", }; let text: String = content .iter() @@ -4785,7 +4785,7 @@ fn preview_segments(segments: &[Segment]) -> String { #[derive(Debug, thiserror::Error)] pub enum PodError { #[error(transparent)] - Worker(#[from] WorkerError), + Engine(#[from] EngineError), #[error(transparent)] Store(#[from] StoreError), @@ -5644,19 +5644,19 @@ mod build_summary_prompt_tests { impl LlmClient for NoopClient { async fn stream( &self, - _request: llm_worker::llm_client::Request, + _request: llm_engine::llm_client::Request, ) -> Result< std::pin::Pin< Box< dyn futures::Stream< Item = Result< - llm_worker::llm_client::event::Event, - llm_worker::llm_client::ClientError, + llm_engine::llm_client::event::Event, + llm_engine::llm_client::ClientError, >, > + Send, >, >, - llm_worker::llm_client::ClientError, + llm_engine::llm_client::ClientError, > { Ok(Box::pin(futures::stream::empty())) } @@ -5679,7 +5679,7 @@ mod build_summary_prompt_tests { let cwd = dir.path().join("workspace"); std::fs::create_dir_all(&cwd).unwrap(); let scope = Scope::writable(&cwd).unwrap(); - let mut pod = Pod::new(manifest, Worker::new(NoopClient), store, cwd, scope) + let mut pod = Pod::new(manifest, Engine::new(NoopClient), store, cwd, scope) .await .unwrap(); pod.ensure_segment_head().unwrap(); @@ -5794,9 +5794,9 @@ mod build_summary_prompt_tests { .len(), expected_truncate_entries ); - assert_eq!(pod.worker().history().len(), 1); + assert_eq!(pod.engine().history().len(), 1); assert_eq!( - pod.worker().history()[0].as_text().unwrap(), + pod.engine().history()[0].as_text().unwrap(), "first message" ); } @@ -5824,18 +5824,18 @@ mod build_summary_prompt_tests { let cwd = dir.path().join("workspace"); std::fs::create_dir_all(&cwd).unwrap(); let scope = Scope::writable(&cwd).unwrap(); - let mut pod = Pod::new(manifest, Worker::new(NoopClient), store, cwd, scope) + let mut pod = Pod::new(manifest, Engine::new(NoopClient), store, cwd, scope) .await .unwrap(); pod.ensure_segment_head().unwrap(); pod.wire_history_persistence(); - pod.worker_mut() + pod.engine_mut() .set_history(vec![Item::tool_call("call-1", "Read", "{}")]); pod.apply_interrupt_prep().unwrap(); - let history = pod.worker().history(); + let history = pod.engine().history(); assert_eq!(history.len(), 3); assert!(matches!(history[1], Item::ToolResult { ref call_id, .. } if call_id == "call-1")); assert!(matches!( @@ -5950,7 +5950,7 @@ mod build_summary_prompt_tests { let mut manifest = minimal_manifest_with_skills(vec![]); manifest.memory = memory_config; let scope = Scope::writable(&cwd).unwrap(); - let mut pod = Pod::new(manifest, Worker::new(NoopClient), store, cwd.clone(), scope) + let mut pod = Pod::new(manifest, Engine::new(NoopClient), store, cwd.clone(), scope) .await .unwrap(); pod.memory_layout = pod @@ -5975,7 +5975,7 @@ mod build_summary_prompt_tests { .unwrap(); pod.set_system_prompt_template(template); pod.ensure_system_prompt_materialized().unwrap(); - pod.worker().get_system_prompt().unwrap().to_string() + pod.engine().get_system_prompt().unwrap().to_string() } fn summary_doc(body: &str) -> String { diff --git a/crates/pod/src/prompt/catalog.rs b/crates/pod/src/prompt/catalog.rs index 2c5fdd9a..8ef7f42a 100644 --- a/crates/pod/src/prompt/catalog.rs +++ b/crates/pod/src/prompt/catalog.rs @@ -1,6 +1,6 @@ //! Central catalog of Pod-level prompt strings. //! -//! Prompts that Pod injects into a Worker (compaction system prompt, +//! Prompts that Pod injects into a Engine (compaction system prompt, //! notification wrapper, interrupt notes, system-prompt trailing //! sections, AGENTS.md truncation notice, ...) are enumerated by //! [`PodPrompt`] and rendered through a single [`PromptCatalog`]. Direct @@ -59,11 +59,11 @@ const INTERNAL_TOML: &str = include_str!("../../../../resources/prompts/internal /// `resources/prompts/internal.toml`; the build fails otherwise. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum PodPrompt { - /// System prompt of the compaction (summary) Worker. + /// System prompt of the compaction (summary) Engine. CompactSystem, - /// System prompt of the memory extract Worker. + /// System prompt of the memory extract Engine. MemoryExtractSystem, - /// System prompt of the memory consolidation (integration + tidy) Worker. + /// System prompt of the memory consolidation (integration + tidy) Engine. MemoryConsolidationSystem, /// Wrapper around an incoming `Method::Notify` message injected into /// the next LLM request context as a transient system message. diff --git a/crates/pod/src/prompt/system.rs b/crates/pod/src/prompt/system.rs index 5a4c581e..0041fbd5 100644 --- a/crates/pod/src/prompt/system.rs +++ b/crates/pod/src/prompt/system.rs @@ -9,7 +9,7 @@ //! the rendered body is appended with a fixed trailing section carrying //! the Pod's `Scope` summary, (if present) the project's `AGENTS.md` //! contents, resident memory sections, and conditional Pod-orchestration -//! guidance, then the whole string is handed to the Worker via +//! guidance, then the whole string is handed to the Engine via //! `set_system_prompt`. Subsequent turns and compactions reuse that //! materialised string verbatim. diff --git a/crates/pod/src/segment_log_sink.rs b/crates/pod/src/segment_log_sink.rs index 906d5005..369d8fe7 100644 --- a/crates/pod/src/segment_log_sink.rs +++ b/crates/pod/src/segment_log_sink.rs @@ -227,7 +227,7 @@ impl Default for SegmentLogSink { #[cfg(test)] mod tests { use super::*; - use llm_worker::llm_client::RequestConfig; + use llm_engine::llm_client::RequestConfig; use session_store::segment_log::now_millis; fn session_start() -> LogEntry { diff --git a/crates/pod/src/shutdown_after_idle.rs b/crates/pod/src/shutdown_after_idle.rs index 0be9c54a..3ab151ed 100644 --- a/crates/pod/src/shutdown_after_idle.rs +++ b/crates/pod/src/shutdown_after_idle.rs @@ -79,7 +79,7 @@ impl Hook for TicketIntakeReadyShutdownHook { #[cfg(test)] mod tests { use super::*; - use llm_worker::tool::ToolOutput; + use llm_engine::tool::ToolOutput; fn tool_result(name: &str, is_error: bool) -> ToolResultSummary { ToolResultSummary { diff --git a/crates/pod/src/spawn/comm_tools.rs b/crates/pod/src/spawn/comm_tools.rs index 57b953b4..f605b82c 100644 --- a/crates/pod/src/spawn/comm_tools.rs +++ b/crates/pod/src/spawn/comm_tools.rs @@ -14,8 +14,8 @@ use std::sync::Arc; use std::time::Duration; use async_trait::async_trait; -use llm_worker::llm_client::types::{ContentPart, Item, Role}; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::llm_client::types::{ContentPart, Item, Role}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use protocol::stream::{JsonLineReader, JsonLineWriter}; use protocol::{ErrorCode, Event, InvokeKind, Method}; use serde::Deserialize; @@ -65,7 +65,7 @@ impl Tool for SendToPodTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: SendToPodInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid SendToPod input: {e}")))?; @@ -130,7 +130,7 @@ impl Tool for ReadPodOutputTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: NameInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid ReadPodOutput input: {e}")))?; @@ -208,7 +208,7 @@ impl Tool for StopPodTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: NameInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid StopPod input: {e}")))?; diff --git a/crates/pod/src/spawn/tool.rs b/crates/pod/src/spawn/tool.rs index 21693d50..a856145e 100644 --- a/crates/pod/src/spawn/tool.rs +++ b/crates/pod/src/spawn/tool.rs @@ -13,7 +13,7 @@ use std::time::Duration; use async_trait::async_trait; use client::PodRuntimeCommand; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use manifest::{ CompactionConfigPartial, DelegationScope, FileUploadLimitsPartial, Permission, PermissionConfigPartial, PodManifest, PodManifestConfig, PodMetaConfig, ProfileDiscovery, @@ -301,7 +301,7 @@ impl Tool for SpawnPodTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: SpawnPodInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid SpawnPod input: {e}")))?; diff --git a/crates/pod/src/ticket_event_notify.rs b/crates/pod/src/ticket_event_notify.rs index cabc946c..71d709a8 100644 --- a/crates/pod/src/ticket_event_notify.rs +++ b/crates/pod/src/ticket_event_notify.rs @@ -245,7 +245,7 @@ mod tests { use crate::PodStatus; use crate::runtime::dir::RuntimeDir; use crate::spawn::registry::SpawnedPodRegistry; - use llm_worker::tool::ToolOutput; + use llm_engine::tool::ToolOutput; use pod_store::FsPodStore; use pod_store::PodMetadata; use protocol::stream::{JsonLineReader, JsonLineWriter}; diff --git a/crates/pod/src/workflow/mod.rs b/crates/pod/src/workflow/mod.rs index aa015dba..07aee771 100644 --- a/crates/pod/src/workflow/mod.rs +++ b/crates/pod/src/workflow/mod.rs @@ -4,11 +4,11 @@ //! dependency Knowledge bodies first, then the Workflow body. Resolution is //! strict for explicit user invocations: missing workflows, non-user-invocable //! workflows, and missing Knowledge requirements are returned as errors before -//! the turn is handed to the Worker. +//! the turn is handed to the Engine. use std::fmt; -use llm_worker::Item; +use llm_engine::Item; use memory::WorkspaceLayout; use memory::schema::split_frontmatter; use workflow_crate::{Slug, WorkflowRegistry}; diff --git a/crates/pod/tests/compact_events_test.rs b/crates/pod/tests/compact_events_test.rs index de3d54a9..22807119 100644 --- a/crates/pod/tests/compact_events_test.rs +++ b/crates/pod/tests/compact_events_test.rs @@ -12,10 +12,10 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use async_trait::async_trait; use futures::Stream; -use llm_worker::Worker; -use llm_worker::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent}; -use llm_worker::llm_client::types::Item; -use llm_worker::llm_client::{ClientError, LlmClient, Request}; +use llm_engine::Engine; +use llm_engine::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent}; +use llm_engine::llm_client::types::Item; +use llm_engine::llm_client::{ClientError, LlmClient, Request}; use pod_store::{CombinedStore, FsPodStore, PodMetadataStore}; use protocol::{Event, Method, RunResult}; use session_store::{FsStore, LogEntry, Store}; @@ -163,7 +163,7 @@ async fn make_pod_with_manifest( let scope = pod::Scope::writable(&pwd).unwrap(); std::mem::forget(pwd_tmp); - let worker = Worker::new(client); + let worker = Engine::new(client); let mut pod = Pod::new(manifest, worker, store, pwd, scope).await.unwrap(); pod.enable_pod_metadata_write_through().unwrap(); pod @@ -189,7 +189,7 @@ fn drain(rx: &mut broadcast::Receiver) -> Vec { /// `SegmentStart.history` carries, by reading the sink mirror directly. fn system_texts_in_sink_session_start( pod: &pod::Pod< - impl llm_worker::llm_client::client::LlmClient + Clone + 'static, + impl llm_engine::llm_client::client::LlmClient + Clone + 'static, impl session_store::Store + Clone + 'static, >, ) -> Vec { @@ -202,7 +202,7 @@ fn system_texts_in_sink_session_start( let item: Item = logged.into(); match item { Item::Message { - role: llm_worker::Role::System, + role: llm_engine::Role::System, content, .. } => Some( @@ -462,7 +462,7 @@ async fn mid_turn_compact_success_broadcasts_start_and_done() { pod.run_text("first").await.unwrap(); let _ = drain(&mut rx); - // Second run: pre_llm_request yields immediately, Worker returns + // Second run: pre_llm_request yields immediately, Engine returns // Yielded, handle_worker_result routes into do_compact_and_resume. pod.run_text("second").await.unwrap(); diff --git a/crates/pod/tests/consolidation_test.rs b/crates/pod/tests/consolidation_test.rs index 4b81d5cf..3e477e21 100644 --- a/crates/pod/tests/consolidation_test.rs +++ b/crates/pod/tests/consolidation_test.rs @@ -20,9 +20,9 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use async_trait::async_trait; use futures::Stream; -use llm_worker::Worker; -use llm_worker::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent}; -use llm_worker::llm_client::{ClientError, LlmClient, Request}; +use llm_engine::Engine; +use llm_engine::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent}; +use llm_engine::llm_client::{ClientError, LlmClient, Request}; use memory::WorkspaceLayout; use memory::extract::{ExtractedPayload, write_staging}; use memory::schema::SourceRef; @@ -169,7 +169,7 @@ async fn make_pod_with( std::mem::forget(store_tmp); let scope = pod::Scope::writable(&pwd).unwrap(); - let worker = Worker::new(client); + let worker = Engine::new(client); Pod::new(manifest, worker, store, pwd, scope).await.unwrap() } @@ -388,7 +388,7 @@ async fn fires_on_threshold_and_cleans_up_consumed_entries() { write_n_staging(&layout, 2); // threshold is 2 — fires. // Sub-worker is given a single text-only response. The consolidation prompt - // tells it to call memory tools; the mock skips those, but `Worker::run` + // tells it to call memory tools; the mock skips those, but `Engine::run` // returns Ok regardless once the LLM closes with a final text. let client = MockClient::new(vec![done("ok")]); let mut pod = make_pod_with(FILES_THRESHOLD_TOML, pwd.path().to_path_buf(), client).await; diff --git a/crates/pod/tests/controller_test.rs b/crates/pod/tests/controller_test.rs index 9b8aa1bd..1c636ac1 100644 --- a/crates/pod/tests/controller_test.rs +++ b/crates/pod/tests/controller_test.rs @@ -4,11 +4,11 @@ use std::sync::{Arc, Mutex}; use async_trait::async_trait; use futures::{Stream, StreamExt}; -use llm_worker::Worker; -use llm_worker::llm_client::event::{ErrorEvent, Event as LlmEvent, ResponseStatus, StatusEvent}; -use llm_worker::llm_client::types::Item; -use llm_worker::llm_client::{ClientError, LlmClient, Request}; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::Engine; +use llm_engine::llm_client::event::{ErrorEvent, Event as LlmEvent, ResponseStatus, StatusEvent}; +use llm_engine::llm_client::types::Item; +use llm_engine::llm_client::{ClientError, LlmClient, Request}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use pod_store::{CombinedStore, FsPodStore}; use session_store::{FsStore, LogEntry}; @@ -53,7 +53,7 @@ fn history_from_sink(handle: &PodHandle) -> Vec { enum MockResponse { /// Emit the events and let the stream terminate naturally. Complete(Vec), - /// Emit the events and then pend forever so the Worker blocks on + /// Emit the events and then pend forever so the Engine blocks on /// `stream.next()` — used to exercise the Cancel/Pause path while a /// turn is actively in flight. Hang(Vec), @@ -183,7 +183,7 @@ async fn make_pod_with_pwd_and_manifest( let scope = manifest::Scope::writable(&pwd).unwrap(); std::mem::forget(pwd_tmp); - let worker = Worker::new(client); + let worker = Engine::new(client); let pod = Pod::new(manifest, worker, store, pwd.clone(), scope) .await .unwrap(); @@ -518,7 +518,7 @@ async fn provider_stream_error_records_run_errored() { !entries.iter().any(|entry| matches!( entry, LogEntry::RunCompleted { - result: llm_worker::WorkerResult::Finished, + result: llm_engine::EngineResult::Finished, .. } )), @@ -854,7 +854,7 @@ async fn run_with_paste_segment_inlines_content_and_emits_typed_user_message() { let echoed = user_input_segments.expect("committed UserInput entry missing"); assert_eq!(echoed, segments, "typed segments must round-trip unchanged"); - // The Worker received a single user message whose text is the + // The Engine received a single user message whose text is the // flattened body — paste content inlined, no chip label. tokio::time::sleep(std::time::Duration::from_millis(50)).await; let requests = client_for_assert.captured_requests(); @@ -1101,7 +1101,7 @@ async fn notify_while_idle_auto_starts_turn_and_injects_system_message() { .collect::>() ); - // The notification must also be persisted into the Worker history + // The notification must also be persisted into the Engine history // (and therefore eventually into history.json), per // tickets/notify-history-persist.md. let history = history_from_sink(&handle); @@ -1638,7 +1638,7 @@ impl Tool for HangingTool { async fn execute( &self, _input: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { std::future::pending::<()>().await; unreachable!() @@ -1681,7 +1681,7 @@ async fn drain_until bool>( #[tokio::test] async fn pause_then_resume_transitions_and_preserves_history_consistency() { // Response 1: hang after opening a text block (no stop / completed), - // so the Worker is parked inside the stream read and `cancel_rx` + // so the Engine is parked inside the stream read and `cancel_rx` // races it cleanly on Method::Pause. let hang = MockResponse::Hang(vec![ LlmEvent::text_block_start(0), @@ -1717,7 +1717,7 @@ async fn pause_then_resume_transitions_and_preserves_history_consistency() { handle.send(Method::Pause).await.unwrap(); // The controller emits RunEnd { Paused } when the - // WorkerError::Cancelled is translated under pause_requested. + // EngineError::Cancelled is translated under pause_requested. assert!( drain_until(&mut rx, std::time::Duration::from_secs(2), |e| matches!( e, @@ -1756,9 +1756,9 @@ async fn pause_then_resume_transitions_and_preserves_history_consistency() { .iter() .filter_map(|i| match i { Item::Message { role, .. } => match role { - llm_worker::Role::User => Some("user"), - llm_worker::Role::Assistant => Some("assistant"), - llm_worker::Role::System => Some("system"), + llm_engine::Role::User => Some("user"), + llm_engine::Role::Assistant => Some("assistant"), + llm_engine::Role::System => Some("system"), }, _ => None, }) @@ -1772,13 +1772,13 @@ async fn pause_then_resume_transitions_and_preserves_history_consistency() { .iter() .find_map(|i| match i { Item::Message { - role: llm_worker::Role::Assistant, + role: llm_engine::Role::Assistant, content, .. } => Some( content .iter() - .map(|p: &llm_worker::ContentPart| p.as_text().to_owned()) + .map(|p: &llm_engine::ContentPart| p.as_text().to_owned()) .collect::>() .join(""), ), @@ -1797,7 +1797,7 @@ async fn pause_then_resume_transitions_and_preserves_history_consistency() { #[tokio::test] async fn paused_then_run_closes_orphan_tool_use_for_next_request() { // Response 1: emit a tool_use block (complete with stop) targeting - // our hanging tool. The Worker commits the ToolCall to history, + // our hanging tool. The Engine commits the ToolCall to history, // then parks inside `execute_tools` waiting on the tool — which is // where Method::Pause catches it. let tool_name = "HangyTool"; @@ -1821,7 +1821,7 @@ async fn paused_then_run_closes_orphan_tool_use_for_next_request() { let client = MockClient::sequential(vec![first, second]); let client_for_assert = client.clone(); let mut pod = make_pod(client).await; - pod.worker_mut() + pod.engine_mut() .register_tool(hanging_tool_definition(tool_name)); let handle = spawn_controller(pod).await; let mut rx = handle.subscribe(); @@ -1829,7 +1829,7 @@ async fn paused_then_run_closes_orphan_tool_use_for_next_request() { handle.send(Method::run_text("first")).await.unwrap(); // Wait for ToolCallDone — the ToolCall is committed to history - // right before the Worker enters tool execution and pends. + // right before the Engine enters tool execution and pends. assert!( drain_until(&mut rx, std::time::Duration::from_secs(2), |e| matches!( e, @@ -1882,21 +1882,21 @@ async fn paused_then_run_closes_orphan_tool_use_for_next_request() { let mut saw_new_user = false; for item in items { match item { - llm_worker::Item::ToolResult { + llm_engine::Item::ToolResult { call_id, summary, .. } if call_id == "call_orphan" => { assert_eq!(summary, "[Interrupted by user]"); saw_synthetic_tool_result = true; } - llm_worker::Item::Message { role, content, .. } - if *role == llm_worker::Role::System => + llm_engine::Item::Message { role, content, .. } + if *role == llm_engine::Role::System => { let text: String = content.iter().map(|p| p.as_text()).collect(); if text.contains("interrupted by the user") { saw_interruption_note = true; } } - llm_worker::Item::Message { role, content, .. } if *role == llm_worker::Role::User => { + llm_engine::Item::Message { role, content, .. } if *role == llm_engine::Role::User => { let text: String = content.iter().map(|p| p.as_text()).collect(); if text.contains("new request") { saw_new_user = true; @@ -1921,13 +1921,13 @@ async fn paused_then_run_closes_orphan_tool_use_for_next_request() { // Also confirm the closure chain is ordered: tool_result for the // orphan precedes the system note, which precedes the new user // message. - let idx = |pred: &dyn Fn(&llm_worker::Item) -> bool| items.iter().position(pred).unwrap(); + let idx = |pred: &dyn Fn(&llm_engine::Item) -> bool| items.iter().position(pred).unwrap(); let tool_result_idx = idx( - &|i| matches!(i, llm_worker::Item::ToolResult { call_id, .. } if call_id == "call_orphan"), + &|i| matches!(i, llm_engine::Item::ToolResult { call_id, .. } if call_id == "call_orphan"), ); let sys_idx = idx(&|i| match i { - llm_worker::Item::Message { - role: llm_worker::Role::System, + llm_engine::Item::Message { + role: llm_engine::Role::System, content, .. } => content @@ -1938,8 +1938,8 @@ async fn paused_then_run_closes_orphan_tool_use_for_next_request() { _ => false, }); let user_idx = idx(&|i| match i { - llm_worker::Item::Message { - role: llm_worker::Role::User, + llm_engine::Item::Message { + role: llm_engine::Role::User, content, .. } => content @@ -1981,7 +1981,7 @@ async fn paused_cancel_abandons_resume_and_next_input_is_fresh_run() { let client = MockClient::sequential(vec![first, second]); let client_for_assert = client.clone(); let mut pod = make_pod(client).await; - pod.worker_mut() + pod.engine_mut() .register_tool(hanging_tool_definition(tool_name)); let handle = spawn_controller(pod).await; let mut rx = handle.subscribe(); @@ -2022,7 +2022,7 @@ async fn paused_cancel_abandons_resume_and_next_input_is_fresh_run() { !entries_after_cancel.iter().any(|entry| matches!( entry, LogEntry::RunCompleted { - result: llm_worker::WorkerResult::Finished, + result: llm_engine::EngineResult::Finished, interrupted: false, .. } @@ -2078,7 +2078,7 @@ async fn paused_cancel_abandons_resume_and_next_input_is_fresh_run() { assert!( items.iter().any(|item| matches!( item, - llm_worker::Item::ToolResult { call_id, summary, .. } + llm_engine::Item::ToolResult { call_id, summary, .. } if call_id == "call_cancelled" && summary == "[Interrupted by user]" )), "paused cancel should close orphan tool_use before future requests: {items:?}" @@ -2086,8 +2086,8 @@ async fn paused_cancel_abandons_resume_and_next_input_is_fresh_run() { assert!( items.iter().any(|item| matches!( item, - llm_worker::Item::Message { - role: llm_worker::Role::System, + llm_engine::Item::Message { + role: llm_engine::Role::System, .. } if item_text_contains(item, "interrupted by the user") )), @@ -2096,8 +2096,8 @@ async fn paused_cancel_abandons_resume_and_next_input_is_fresh_run() { assert!( items.iter().any(|item| matches!( item, - llm_worker::Item::Message { - role: llm_worker::Role::User, + llm_engine::Item::Message { + role: llm_engine::Role::User, .. } if item_text_contains(item, "fresh request") )), diff --git a/crates/pod/tests/pod_comm_tools_test.rs b/crates/pod/tests/pod_comm_tools_test.rs index 6bd63e93..e7e5fdd8 100644 --- a/crates/pod/tests/pod_comm_tools_test.rs +++ b/crates/pod/tests/pod_comm_tools_test.rs @@ -11,8 +11,8 @@ use std::path::{Path, PathBuf}; use std::sync::{Arc, LazyLock, Mutex}; -use llm_worker::llm_client::types::{ContentPart, Item, Role}; -use llm_worker::tool::ToolOutput; +use llm_engine::llm_client::types::{ContentPart, Item, Role}; +use llm_engine::tool::ToolOutput; use manifest::{Permission, Scope, ScopeRule, SharedScope}; use pod::runtime::dir::{RuntimeDir, SpawnedPodRecord}; use pod::runtime::pod_registry::{self, LockFileGuard}; diff --git a/crates/pod/tests/session_metrics_test.rs b/crates/pod/tests/session_metrics_test.rs index 36312215..08ee8a8a 100644 --- a/crates/pod/tests/session_metrics_test.rs +++ b/crates/pod/tests/session_metrics_test.rs @@ -21,10 +21,10 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use async_trait::async_trait; use futures::Stream; -use llm_worker::Worker; -use llm_worker::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent, UsageEvent}; -use llm_worker::llm_client::{ClientError, LlmClient, Request}; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::Engine; +use llm_engine::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent, UsageEvent}; +use llm_engine::llm_client::{ClientError, LlmClient, Request}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use pod_store::{CombinedStore, FsPodStore}; use session_metrics::{DOMAIN, Metric, metrics_from_extensions}; use session_store::{FsStore, LogEntry, SegmentId, SessionId, Store, StoreError, TraceEntry}; @@ -82,7 +82,7 @@ impl Tool for BigContentTool { async fn execute( &self, _input: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { Ok(ToolOutput { summary: self.summary.into(), @@ -187,7 +187,7 @@ async fn make_pod( let pwd = pwd_tmp.path().to_path_buf(); let scope = pod::Scope::writable(&pwd).unwrap(); - let mut worker = Worker::new(client); + let mut worker = Engine::new(client); worker.register_tool(big_content_tool_definition(tool_name)); let pod = Pod::new(manifest, worker, store, pwd, scope).await.unwrap(); @@ -448,7 +448,7 @@ async fn metric_write_failure_emits_warn_alert_and_does_not_abort_run() { // protected token budget covers the only user message). That is enough to drive // the failure path: at least one metric attempts to write. let client = MockClient::new(vec![text_response_with_cache("hi", 0, 0)]); - let worker = Worker::new(client); + let worker = Engine::new(client); let mut pod = Pod::new(manifest, worker, store.clone(), pwd, scope) .await .unwrap(); @@ -517,7 +517,7 @@ permission = "write" let pwd_tmp = tempfile::tempdir().unwrap(); let pwd = pwd_tmp.path().to_path_buf(); let scope = pod::Scope::writable(&pwd).unwrap(); - let worker = Worker::new(client); + let worker = Engine::new(client); let mut pod = Pod::new(manifest, worker, store.clone(), pwd, scope) .await .unwrap(); diff --git a/crates/pod/tests/spawn_pod_test.rs b/crates/pod/tests/spawn_pod_test.rs index a175da4b..010a38f2 100644 --- a/crates/pod/tests/spawn_pod_test.rs +++ b/crates/pod/tests/spawn_pod_test.rs @@ -10,7 +10,7 @@ use std::path::{Path, PathBuf}; use std::sync::{LazyLock, Mutex}; use client::PodRuntimeCommand; -use llm_worker::tool::{ToolError, ToolOutput}; +use llm_engine::tool::{ToolError, ToolOutput}; use manifest::{ AuthRef, ModelManifest, Permission, PodManifest, PodManifestConfig, PodMetaConfig, SchemeKind, Scope, ScopeConfig, ScopeRule, SharedScope, diff --git a/crates/pod/tests/system_prompt_template_test.rs b/crates/pod/tests/system_prompt_template_test.rs index c9b32ca7..21dd66e3 100644 --- a/crates/pod/tests/system_prompt_template_test.rs +++ b/crates/pod/tests/system_prompt_template_test.rs @@ -5,9 +5,9 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use async_trait::async_trait; use futures::Stream; -use llm_worker::Worker; -use llm_worker::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent}; -use llm_worker::llm_client::{ClientError, LlmClient, Request}; +use llm_engine::Engine; +use llm_engine::llm_client::event::{Event as LlmEvent, ResponseStatus, StatusEvent}; +use llm_engine::llm_client::{ClientError, LlmClient, Request}; use pod_store::{CombinedStore, FsPodStore}; use session_store::{FsStore, LogEntry, Store}; @@ -122,7 +122,7 @@ async fn make_pod_with_body( let loader = PromptLoader::new(Some(user_prompts_tmp.path().to_path_buf()), None); std::mem::forget(user_prompts_tmp); - let worker = Worker::new(client); + let worker = Engine::new(client); let mut pod = Pod::new(manifest, worker, store, pwd.clone(), scope).await?; let template = SystemPromptTemplate::parse("$user/test", loader) @@ -154,7 +154,7 @@ async fn template_is_not_materialised_before_first_run() { let client = MockClient::new(vec![single_text_events("ok")]); let (pod, _pwd) = make_pod_with_body("hello", client).await.unwrap(); // Before first run, worker still has no system prompt. - assert!(pod.worker().get_system_prompt().is_none()); + assert!(pod.engine().get_system_prompt().is_none()); } #[tokio::test] @@ -168,7 +168,7 @@ async fn materialise_on_first_turn_populates_worker() { .unwrap(); pod.run_text("hi").await.unwrap(); let rendered = pod - .worker() + .engine() .get_system_prompt() .expect("system prompt materialised") .to_string(); @@ -222,9 +222,9 @@ async fn materialise_runs_only_once_across_turns() { .await .unwrap(); pod.run_text("one").await.unwrap(); - let first = pod.worker().get_system_prompt().unwrap().to_string(); + let first = pod.engine().get_system_prompt().unwrap().to_string(); pod.run_text("two").await.unwrap(); - let second = pod.worker().get_system_prompt().unwrap().to_string(); + let second = pod.engine().get_system_prompt().unwrap().to_string(); assert_eq!(first, second); } @@ -235,7 +235,7 @@ async fn agents_md_is_injected_as_trailing_section_when_present() { std::fs::write(pwd.join("AGENTS.md"), "# project rules\nbe kind").unwrap(); pod.run_text("hi").await.unwrap(); - let rendered = pod.worker().get_system_prompt().unwrap().to_string(); + let rendered = pod.engine().get_system_prompt().unwrap().to_string(); assert!(rendered.starts_with("BODY")); assert!(rendered.contains("## Project instructions (AGENTS.md)")); assert!(rendered.contains("# project rules")); @@ -247,7 +247,7 @@ async fn agents_md_absent_omits_trailing_section() { let client = MockClient::new(vec![single_text_events("ok")]); let (mut pod, _pwd) = make_pod_with_body("BODY", client).await.unwrap(); pod.run_text("hi").await.unwrap(); - let rendered = pod.worker().get_system_prompt().unwrap().to_string(); + let rendered = pod.engine().get_system_prompt().unwrap().to_string(); assert!(!rendered.contains("## Project instructions")); assert!(!rendered.contains("AGENTS.md")); } @@ -266,7 +266,7 @@ async fn agents_md_not_reread_after_compact() { std::fs::write(&agents_path, "original").unwrap(); pod.run_text("first").await.unwrap(); - let before = pod.worker().get_system_prompt().unwrap().to_string(); + let before = pod.engine().get_system_prompt().unwrap().to_string(); assert!(before.contains("original")); pod.run_text("second").await.unwrap(); @@ -274,12 +274,12 @@ async fn agents_md_not_reread_after_compact() { // system prompt either on a subsequent turn or across compaction. std::fs::write(&agents_path, "mutated").unwrap(); pod.compact(0).await.unwrap(); - let after_compact = pod.worker().get_system_prompt().unwrap().to_string(); + let after_compact = pod.engine().get_system_prompt().unwrap().to_string(); assert!(after_compact.contains("original")); assert!(!after_compact.contains("mutated")); pod.run_text("third").await.unwrap(); - let after_third = pod.worker().get_system_prompt().unwrap().to_string(); + let after_third = pod.engine().get_system_prompt().unwrap().to_string(); assert!(after_third.contains("original")); assert!(!after_third.contains("mutated")); } @@ -329,14 +329,14 @@ async fn compact_preserves_system_prompt() { .unwrap(); pod.run_text("first").await.unwrap(); - let before = pod.worker().get_system_prompt().unwrap().to_string(); + let before = pod.engine().get_system_prompt().unwrap().to_string(); pod.run_text("second").await.unwrap(); pod.compact(0).await.unwrap(); - let after = pod.worker().get_system_prompt().unwrap().to_string(); + let after = pod.engine().get_system_prompt().unwrap().to_string(); assert_eq!(before, after); pod.run_text("third").await.unwrap(); - assert_eq!(pod.worker().get_system_prompt().unwrap(), after.as_str()); + assert_eq!(pod.engine().get_system_prompt().unwrap(), after.as_str()); } diff --git a/crates/protocol/README.md b/crates/protocol/README.md index b1b5af61..939d4253 100644 --- a/crates/protocol/README.md +++ b/crates/protocol/README.md @@ -16,7 +16,7 @@ Does not own: - Unix socket implementation details (`client`, `pod`) - TUI rendering (`tui`) -- Worker history semantics (`llm-worker`) +- Engine history semantics (`llm-engine`) - durable storage (`session-store`, `pod-store`) ## Design notes diff --git a/crates/protocol/src/lib.rs b/crates/protocol/src/lib.rs index 7dde4707..8d40e215 100644 --- a/crates/protocol/src/lib.rs +++ b/crates/protocol/src/lib.rs @@ -113,7 +113,7 @@ pub enum PodEvent { /// Child finished one turn and is back to IDLE. TurnEnded { pod_name: String }, - /// Worker execution error occurred inside the child's turn. + /// Engine execution error occurred inside the child's turn. /// /// Limited to worker runtime failures (provider / tool errors) — /// does not include transient method-rejection responses such as @@ -327,9 +327,9 @@ pub enum Event { /// result lands, a user interrupts, etc.), the next LLM call belongs /// to a new AgentTurn. /// - /// `turn` is the AgentTurn index from `Worker::turn_count`. + /// `turn` is the AgentTurn index from `Engine::turn_count`. /// - /// Currently retry is not yet implemented (`llm-worker-stream-continuation`) + /// Currently retry is not yet implemented (`llm-engine-stream-continuation`) /// so AgentTurn and `LlmCall` fire 1:1, but the contract here is /// the AgentTurn boundary; consumers that want per-LLM-call signals /// must subscribe to `LlmCallStart` / `LlmCallEnd` instead. @@ -347,7 +347,7 @@ pub enum Event { /// they fire 1:1 because retry is not implemented. /// /// `llm_call` is the worker-wide running counter from - /// `Worker::llm_call_count`. + /// `Engine::llm_call_count`. LlmCallStart { llm_call: usize, }, @@ -597,7 +597,7 @@ pub enum AlertLevel { #[serde(rename_all = "snake_case")] pub enum AlertSource { Pod, - Worker, + Engine, Compactor, AgentsMd, } diff --git a/crates/provider/Cargo.toml b/crates/provider/Cargo.toml index 9f049af3..562d8061 100644 --- a/crates/provider/Cargo.toml +++ b/crates/provider/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true async-trait = { workspace = true } base64 = "0.22.1" chrono = { version = "0.4", default-features = false, features = ["serde", "clock"] } -llm-worker = { workspace = true } +llm-engine = { workspace = true } manifest = { workspace = true } secrets = { workspace = true } reqwest = { version = "0.13", features = ["json", "native-tls"] } diff --git a/crates/provider/README.md b/crates/provider/README.md index 8835c1d6..5ae0c361 100644 --- a/crates/provider/README.md +++ b/crates/provider/README.md @@ -2,7 +2,7 @@ ## Role -`provider` resolves model/provider configuration and constructs provider-specific LLM clients for `llm-worker`. +`provider` resolves model/provider configuration and constructs provider-specific LLM clients for `llm-engine`. ## Boundaries @@ -16,14 +16,14 @@ Owns: Does not own: -- Worker turn lifecycle (`llm-worker`) +- Engine turn lifecycle (`llm-engine`) - secret storage internals (`secrets`) - Pod lifecycle (`pod`) - product CLI parsing (`yoi`) ## Design notes -Provider API facts drift. Keep wire-format, auth, catalog, and capability differences here so Worker semantics remain stable. +Provider API facts drift. Keep wire-format, auth, catalog, and capability differences here so Engine semantics remain stable. Codex OAuth is a separate integration from normal provider secret refs because its local file shape and lifecycle differ. diff --git a/crates/provider/src/catalog.rs b/crates/provider/src/catalog.rs index f9356007..47de0036 100644 --- a/crates/provider/src/catalog.rs +++ b/crates/provider/src/catalog.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; -use llm_worker::llm_client::capability::ModelCapability; +use llm_engine::llm_client::capability::ModelCapability; use manifest::{AuthRef, ModelManifest, SchemeKind}; use serde::{Deserialize, Serialize}; diff --git a/crates/provider/src/codex_oauth/error.rs b/crates/provider/src/codex_oauth/error.rs index 92d67842..06a7377a 100644 --- a/crates/provider/src/codex_oauth/error.rs +++ b/crates/provider/src/codex_oauth/error.rs @@ -6,7 +6,7 @@ use std::path::PathBuf; -use llm_worker::llm_client::ClientError; +use llm_engine::llm_client::ClientError; use thiserror::Error; #[derive(Debug, Error)] diff --git a/crates/provider/src/codex_oauth/mod.rs b/crates/provider/src/codex_oauth/mod.rs index 22d4ef7d..2df7b916 100644 --- a/crates/provider/src/codex_oauth/mod.rs +++ b/crates/provider/src/codex_oauth/mod.rs @@ -4,8 +4,8 @@ //! //! 設計: //! -//! - llm-worker は [`AuthProvider`] trait しか知らず、実体である -//! [`CodexAuthProvider`] はこのクレートに置く(feedback_llm_worker_scope) +//! - llm-engine は [`AuthProvider`] trait しか知らず、実体である +//! [`CodexAuthProvider`] はこのクレートに置く(feedback_llm_engine_scope) //! - access_token JWT の `exp` を読み、`now` 以下で proactive refresh //! (Codex CLI と同じバッファなし) //! - 並行する Codex CLI / 別 yoi の refresh と取り違えないよう、 @@ -23,7 +23,7 @@ use std::sync::Arc; use async_trait::async_trait; use chrono::{Duration, Utc}; -use llm_worker::llm_client::{ClientError, auth::AuthProvider}; +use llm_engine::llm_client::{ClientError, auth::AuthProvider}; use reqwest::header::{HeaderName, HeaderValue}; use tokio::sync::Mutex; diff --git a/crates/provider/src/lib.rs b/crates/provider/src/lib.rs index 4609a8d4..cef3906d 100644 --- a/crates/provider/src/lib.rs +++ b/crates/provider/src/lib.rs @@ -10,7 +10,7 @@ //! default_capability > scheme 既定 の順でフォールバック(上位 3 段は //! `catalog::resolve_model_manifest` が [`ModelConfig`] に詰め込む) //! -//! llm-worker は低レベル基盤に留める方針なので、高レベル側で必要に +//! llm-engine は低レベル基盤に留める方針なので、高レベル側で必要に //! なる認証ストア解決(Codex OAuth の `~/.codex/auth.json` 読取等)は //! このクレートに追加する。 @@ -19,7 +19,7 @@ pub mod codex_oauth; use std::sync::Arc; -use llm_worker::llm_client::{ +use llm_engine::llm_client::{ LlmClient, capability::ModelCapability, scheme::{ diff --git a/crates/session-metrics/README.md b/crates/session-metrics/README.md index 78ff7013..7358ec7f 100644 --- a/crates/session-metrics/README.md +++ b/crates/session-metrics/README.md @@ -14,7 +14,7 @@ Owns: Does not own: -- prompt context packing (`llm-worker`) +- prompt context packing (`llm-engine`) - generated memory contents (`memory`) - provider billing semantics (`provider`) - UI status rendering (`tui`) diff --git a/crates/session-store/Cargo.toml b/crates/session-store/Cargo.toml index e9f4da8f..90d49a47 100644 --- a/crates/session-store/Cargo.toml +++ b/crates/session-store/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true license.workspace = true [dependencies] -llm-worker = { workspace = true } +llm-engine = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } uuid = { workspace = true, features = ["v7", "serde"] } diff --git a/crates/session-store/README.md b/crates/session-store/README.md index 187adec2..40bd41f8 100644 --- a/crates/session-store/README.md +++ b/crates/session-store/README.md @@ -10,7 +10,7 @@ Owns: - session identifiers and segment lineage - JSONL log entries for replayable conversation/runtime history -- restoring Worker/session state from committed records +- restoring Engine/session state from committed records - schema surfaces that should make drift compile-visible Does not own: diff --git a/crates/session-store/src/event_trace.rs b/crates/session-store/src/event_trace.rs index e8226344..627b2339 100644 --- a/crates/session-store/src/event_trace.rs +++ b/crates/session-store/src/event_trace.rs @@ -7,7 +7,7 @@ //! //! Disabled by default. Enable via `SessionConfig::record_event_trace`. -use llm_worker::llm_client::event::Event; +use llm_engine::llm_client::event::Event; use serde::{Deserialize, Serialize}; use serde_json::Value; diff --git a/crates/session-store/src/lib.rs b/crates/session-store/src/lib.rs index de383648..82bd5c94 100644 --- a/crates/session-store/src/lib.rs +++ b/crates/session-store/src/lib.rs @@ -6,12 +6,12 @@ //! belonging to the same logical conversation. Each Segment is recorded //! as a sequence of [`LogEntry`] values, one per line in a `.jsonl` //! file. Reading a segment log and collecting entries reconstructs the -//! Worker state at that segment — no separate snapshots or checkpoints +//! Engine state at that segment — no separate snapshots or checkpoints //! needed. Compaction and fork operations mint a fresh Segment within //! the same Session. //! //! This crate provides free functions for persistence operations. -//! The caller (typically Pod) holds the Worker directly and calls these +//! The caller (typically Pod) holds the Engine directly and calls these //! functions after state-mutating operations. //! //! Debug-mode [`TraceEntry`] records capture raw stream events in a separate @@ -40,8 +40,8 @@ pub mod system_item; pub use event_trace::{TraceEntry, TracePayload}; pub use fs_store::FsStore; -pub use llm_worker::UsageRecord; -pub use llm_worker::llm_client::types::{ContentPart, Item, Role}; +pub use llm_engine::UsageRecord; +pub use llm_engine::llm_client::types::{ContentPart, Item, Role}; pub use logged_item::{LoggedContentPart, LoggedItem, LoggedRole, from_logged, to_logged}; pub use segment::{ SegmentStartState, append_entry, append_system_item, classify_history_item, diff --git a/crates/session-store/src/logged_item.rs b/crates/session-store/src/logged_item.rs index fb669039..1079343c 100644 --- a/crates/session-store/src/logged_item.rs +++ b/crates/session-store/src/logged_item.rs @@ -1,4 +1,4 @@ -//! Persistence-stable mirror of `llm_worker::Item`. +//! Persistence-stable mirror of `llm_engine::Item`. //! //! `LogEntry` does not embed `Item` directly because that couples the on-disk //! schema to the LLM worker's internal type — a field rename or addition there @@ -12,7 +12,7 @@ //! `Reasoning::encrypted_content` is preserved because OpenAI Responses ZDR //! requires it on stateless re-send. -use llm_worker::llm_client::types::{ContentPart, Item, Role}; +use llm_engine::llm_client::types::{ContentPart, Item, Role}; use serde::{Deserialize, Serialize}; fn is_false(value: &bool) -> bool { diff --git a/crates/session-store/src/segment.rs b/crates/session-store/src/segment.rs index d776a5ac..ab044148 100644 --- a/crates/session-store/src/segment.rs +++ b/crates/session-store/src/segment.rs @@ -1,7 +1,7 @@ //! Free functions for segment persistence operations. //! -//! These functions record and restore segment state without owning a Worker. -//! The caller (typically Pod) holds the Worker directly and calls these +//! These functions record and restore segment state without owning a Engine. +//! The caller (typically Pod) holds the Engine directly and calls these //! functions after state-mutating operations. use crate::logged_item::{LoggedItem, to_logged}; @@ -9,9 +9,9 @@ use crate::segment_log::{self, LogEntry, SegmentOrigin}; use crate::store::{Store, StoreError}; use crate::system_item::SystemItem; use crate::{SegmentId, SessionId}; -use llm_worker::WorkerResult; -use llm_worker::llm_client::RequestConfig; -use llm_worker::llm_client::types::Item; +use llm_engine::EngineResult; +use llm_engine::llm_client::RequestConfig; +use llm_engine::llm_client::types::Item; use protocol::Segment; /// State snapshot for creating a SegmentStart entry. @@ -89,7 +89,7 @@ pub fn create_compacted_segment( /// Restore segment state from a stored log. /// /// Returns the reconstructed state. The caller is responsible for -/// applying it to a Worker. +/// applying it to a Engine. pub fn restore( store: &impl Store, session_id: SessionId, @@ -287,12 +287,12 @@ pub fn save_turn_end( ) } -/// Log a `RunCompleted` entry — `run()` / `resume()` returned `Ok(WorkerResult)`. +/// Log a `RunCompleted` entry — `run()` / `resume()` returned `Ok(EngineResult)`. pub fn save_run_completed( store: &impl Store, session_id: SessionId, segment_id: SegmentId, - result: WorkerResult, + result: EngineResult, interrupted: bool, ) -> Result<(), StoreError> { append_entry( @@ -307,9 +307,9 @@ pub fn save_run_completed( ) } -/// Log a `RunErrored` entry — `run()` / `resume()` returned `Err(WorkerError)`. +/// Log a `RunErrored` entry — `run()` / `resume()` returned `Err(EngineError)`. /// -/// `WorkerError` is not `Serialize`, so the caller passes a lossy +/// `EngineError` is not `Serialize`, so the caller passes a lossy /// `to_string()` rendering as `message`. pub fn save_run_errored( store: &impl Store, diff --git a/crates/session-store/src/segment_log.rs b/crates/session-store/src/segment_log.rs index 9e5cef92..173b701e 100644 --- a/crates/session-store/src/segment_log.rs +++ b/crates/session-store/src/segment_log.rs @@ -3,14 +3,14 @@ //! Each [`LogEntry`] represents a single state transition within one //! segment, serialized as one line in a `.jsonl` file. Reading all //! entries and collecting them via [`collect_state`] reconstructs the -//! full [`Worker`] state at that segment. +//! full [`Engine`] state at that segment. //! //! The on-disk format is one `LogEntry` per line — entries are positionally //! ordered. Fork lineage references between segments use turn-number indices //! (`SegmentOrigin.at_turn_index`) rather than per-entry hashes. -use llm_worker::llm_client::types::{Item, RequestConfig}; -use llm_worker::{UsageRecord, WorkerResult}; +use llm_engine::llm_client::types::{Item, RequestConfig}; +use llm_engine::{EngineResult, UsageRecord}; use protocol::{InvokeKind, Segment}; use serde::{Deserialize, Serialize}; @@ -19,7 +19,7 @@ use crate::system_item::SystemItem; /// A single segment log entry, serialized as one JSONL line. /// -/// Variants correspond to specific mutation points in `Worker`: +/// Variants correspond to specific mutation points in `Engine`: /// - `SegmentStart` — always the first entry; captures initial state /// - `Invoke` — IDLE → active marker (start of a new self-driving cycle) /// - `UserInput` / `AssistantItem` / `ToolResult` / `SystemItem` — history appends @@ -98,16 +98,16 @@ pub enum LogEntry { /// Turn boundary. Records the turn count after increment. TurnEnd { ts: u64, turn_count: usize }, - /// `run()` / `resume()` が `WorkerResult` で正常終了した。 + /// `run()` / `resume()` が `EngineResult` で正常終了した。 /// Audit-only metadata: replay は `interrupted` のみ反映する。 RunCompleted { ts: u64, interrupted: bool, - result: WorkerResult, + result: EngineResult, }, - /// `run()` / `resume()` が `WorkerError` で終了した。 - /// `WorkerError` は `Serialize` 不可なので `message` のみ lossy 保持する。 + /// `run()` / `resume()` が `EngineError` で終了した。 + /// `EngineError` は `Serialize` 不可なので `message` のみ lossy 保持する。 /// Audit-only metadata: replay は `interrupted` のみ反映する。 RunErrored { ts: u64, @@ -360,7 +360,7 @@ mod tests { LogEntry::RunCompleted { ts: 3200, interrupted: false, - result: WorkerResult::Finished, + result: EngineResult::Finished, }, ]); assert_eq!(state.history.len(), 2); @@ -593,7 +593,7 @@ mod tests { LogEntry::RunCompleted { ts: 100, interrupted: true, - result: WorkerResult::Paused, + result: EngineResult::Paused, }, LogEntry::PausedTurnAbandoned { ts: 200 }, ]); @@ -711,14 +711,14 @@ mod tests { }, parsed, ]); - // Worker history gets a flattened user_message item. + // Engine history gets a flattened user_message item. assert_eq!(state.history.len(), 1); match &state.history[0] { Item::Message { role, content, .. } => { - assert!(matches!(role, llm_worker::Role::User)); + assert!(matches!(role, llm_engine::Role::User)); assert_eq!(content.len(), 1); match &content[0] { - llm_worker::ContentPart::Text { text } => { + llm_engine::ContentPart::Text { text } => { assert_eq!(text, "see line1\nline2@src/main.rs"); } other => panic!("unexpected content: {other:?}"), diff --git a/crates/session-store/src/store.rs b/crates/session-store/src/store.rs index ff5489fc..065f1e6f 100644 --- a/crates/session-store/src/store.rs +++ b/crates/session-store/src/store.rs @@ -6,7 +6,7 @@ //! //! Sync (rather than async) is intentional: a segment log append is a single //! `< 1 KiB` line on local fs and completes well below a millisecond. Going -//! through `tokio::fs` would force every caller — including `Worker`'s sync +//! through `tokio::fs` would force every caller — including `Engine`'s sync //! `on_history_append` callback — to bridge sync → async via a channel + //! drain task. Keeping the store sync lets the worker callback, Pod commit //! paths, and `PodInterceptor` all share one direct `append_entry` call. diff --git a/crates/session-store/src/system_item.rs b/crates/session-store/src/system_item.rs index 6e75bac2..b6377f58 100644 --- a/crates/session-store/src/system_item.rs +++ b/crates/session-store/src/system_item.rs @@ -18,7 +18,7 @@ //! preserved only on the log/wire side; the LLM still sees plain //! system-message text. -use llm_worker::llm_client::types::Item; +use llm_engine::llm_client::types::Item; use protocol::PodEvent; use serde::{Deserialize, Serialize}; diff --git a/crates/session-store/tests/common/mod.rs b/crates/session-store/tests/common/mod.rs index 12bbe7c6..9e2fb909 100644 --- a/crates/session-store/tests/common/mod.rs +++ b/crates/session-store/tests/common/mod.rs @@ -6,8 +6,8 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use async_trait::async_trait; use futures::Stream; -use llm_worker::llm_client::event::Event; -use llm_worker::llm_client::{ClientError, LlmClient, Request}; +use llm_engine::llm_client::event::Event; +use llm_engine::llm_client::{ClientError, LlmClient, Request}; /// A mock LLM client that replays pre-defined event sequences. #[derive(Clone)] diff --git a/crates/session-store/tests/fs_store_test.rs b/crates/session-store/tests/fs_store_test.rs index c5d0b9b0..1b940c05 100644 --- a/crates/session-store/tests/fs_store_test.rs +++ b/crates/session-store/tests/fs_store_test.rs @@ -1,5 +1,5 @@ -use llm_worker::WorkerResult; -use llm_worker::llm_client::types::{Item, RequestConfig}; +use llm_engine::EngineResult; +use llm_engine::llm_client::types::{Item, RequestConfig}; use session_store::{ FsStore, LogEntry, Store, TraceEntry, collect_state, new_segment_id, new_session_id, }; @@ -48,7 +48,7 @@ fn round_trip_write_and_read() { LogEntry::RunCompleted { ts: 3200, interrupted: false, - result: WorkerResult::Finished, + result: EngineResult::Finished, }, ]; @@ -175,8 +175,8 @@ fn trace_entries_in_separate_file() { turn: 0, llm_call: Some(0), payload: session_store::TracePayload::StreamEvent { - event: llm_worker::llm_client::event::Event::Ping( - llm_worker::llm_client::event::PingEvent { timestamp: None }, + event: llm_engine::llm_client::event::Event::Ping( + llm_engine::llm_client::event::PingEvent { timestamp: None }, ), }, }; diff --git a/crates/session-store/tests/session_test.rs b/crates/session-store/tests/session_test.rs index dc8632c9..4f764050 100644 --- a/crates/session-store/tests/session_test.rs +++ b/crates/session-store/tests/session_test.rs @@ -4,11 +4,11 @@ use std::sync::Arc; use async_trait::async_trait; use common::MockLlmClient; -use llm_worker::Worker; -use llm_worker::interceptor::{Interceptor, TurnEndAction}; -use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent}; -use llm_worker::llm_client::types::{Item, RequestConfig}; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::Engine; +use llm_engine::interceptor::{Interceptor, TurnEndAction}; +use llm_engine::llm_client::event::{Event, ResponseStatus, StatusEvent}; +use llm_engine::llm_client::types::{Item, RequestConfig}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use session_store::{FsStore, LogEntry, SegmentStartState, Store, collect_state}; // ============================================================================= @@ -57,7 +57,7 @@ impl Tool for MockWeatherTool { async fn execute( &self, _input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { Ok("Sunny, 25C".to_string().into()) } @@ -97,12 +97,12 @@ fn make_store() -> (tempfile::TempDir, FsStore) { /// Run a worker turn and persist via session-store functions. /// Takes ownership of the worker (needed for lock/unlock) and returns it. async fn run_and_persist( - worker: Worker, + worker: Engine, store: &FsStore, session_id: session_store::SessionId, segment_id: session_store::SegmentId, input: &str, -) -> (Worker, llm_worker::WorkerResult) { +) -> (Engine, llm_engine::EngineResult) { // Mirror Pod's run-entry contract: log the user input as segments // before the worker pushes its flattened user_message; save_delta // skips the resulting user_message item to avoid double-write. @@ -159,7 +159,7 @@ async fn run_and_persist( async fn session_run_logs_entries() { let (_dir, store) = make_store(); let client = MockLlmClient::new(simple_text_events()); - let worker = Worker::new(client); + let worker = Engine::new(client); let (sid, segid) = session_store::create_segment( &store, @@ -191,7 +191,7 @@ async fn session_run_logs_entries() { matches!( e, LogEntry::RunCompleted { - result: llm_worker::WorkerResult::Finished, + result: llm_engine::EngineResult::Finished, .. } ) @@ -203,7 +203,7 @@ async fn session_run_logs_entries() { async fn session_restore_round_trip() { let (_dir, store) = make_store(); let client = MockLlmClient::new(simple_text_events()); - let mut worker = Worker::new(client); + let mut worker = Engine::new(client); worker.set_system_prompt("You are helpful."); let (sid, segid) = session_store::create_segment( @@ -242,7 +242,7 @@ async fn session_restore_round_trip() { async fn session_run_with_tool_call() { let (_dir, store) = make_store(); let client = MockLlmClient::with_responses(tool_call_events()); - let mut worker = Worker::new(client); + let mut worker = Engine::new(client); worker.register_tool(weather_tool_definition()); let (sid, segid) = session_store::create_segment( @@ -276,7 +276,7 @@ async fn session_resume_after_pause() { // First run: tool call with pause policy → Paused let client = MockLlmClient::with_responses(tool_call_events()); - let mut worker = Worker::new(client); + let mut worker = Engine::new(client); worker.register_tool(weather_tool_definition()); worker.set_interceptor(PausePolicy); @@ -291,7 +291,7 @@ async fn session_resume_after_pause() { .unwrap(); let (_worker, result) = run_and_persist(worker, &store, sid, segid, "Weather?").await; - assert!(matches!(result, llm_worker::WorkerResult::Paused)); + assert!(matches!(result, llm_engine::EngineResult::Paused)); // Check RunCompleted is Paused let entries = store.read_all(sid, segid).unwrap(); @@ -299,7 +299,7 @@ async fn session_resume_after_pause() { matches!( e, LogEntry::RunCompleted { - result: llm_worker::WorkerResult::Paused, + result: llm_engine::EngineResult::Paused, .. } ) @@ -315,7 +315,7 @@ async fn session_resume_after_pause() { async fn session_fork_creates_new_session() { let (_dir, store) = make_store(); let client = MockLlmClient::new(simple_text_events()); - let mut worker = Worker::new(client); + let mut worker = Engine::new(client); worker.set_system_prompt("System prompt"); let (sid, segid) = session_store::create_segment( @@ -357,7 +357,7 @@ async fn session_fork_creates_new_session() { async fn session_fork_at_truncates_within_session() { let (_dir, store) = make_store(); let client = MockLlmClient::new(simple_text_events()); - let worker = Worker::new(client); + let worker = Engine::new(client); let (sid, segid) = session_store::create_segment( &store, @@ -402,7 +402,7 @@ async fn session_fork_at_truncates_within_session() { async fn session_config_changed_logged() { let (_dir, store) = make_store(); let client = MockLlmClient::new(vec![]); - let mut worker = Worker::new(client); + let mut worker = Engine::new(client); let (sid, segid) = session_store::create_segment( &store, @@ -435,7 +435,7 @@ async fn session_auto_forks_on_conflict() { // Create a segment let client_a = MockLlmClient::new(simple_text_events()); - let worker_a = Worker::new(client_a); + let worker_a = Engine::new(client_a); let (sid, original_segid) = session_store::create_segment( &store, @@ -519,7 +519,7 @@ async fn session_auto_forks_on_conflict() { async fn nested_past_fork_leaves_ancestors_immutable() { let (_dir, store) = make_store(); let client = MockLlmClient::new(simple_text_events()); - let worker = Worker::new(client); + let worker = Engine::new(client); let (sid, root_segid) = session_store::create_segment( &store, diff --git a/crates/ticket/Cargo.toml b/crates/ticket/Cargo.toml index bfebe1c1..fd4d318f 100644 --- a/crates/ticket/Cargo.toml +++ b/crates/ticket/Cargo.toml @@ -9,7 +9,7 @@ project-record = { workspace = true } async-trait = { workspace = true } chrono = { version = "0.4", default-features = false, features = ["clock"] } fs4 = { workspace = true, features = ["sync"] } -llm-worker = { workspace = true } +llm-engine = { workspace = true } schemars = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/crates/ticket/src/tool.rs b/crates/ticket/src/tool.rs index c7be9a92..ac8098e9 100644 --- a/crates/ticket/src/tool.rs +++ b/crates/ticket/src/tool.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::{Deserialize, Serialize}; use serde_json::{Value, json}; @@ -633,7 +633,7 @@ impl Tool for TicketCreateTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketCreateParams = parse_input("TicketCreate", input_json)?; let mut input = NewTicket::new(params.title); @@ -667,7 +667,7 @@ impl Tool for TicketListTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketListParams = parse_input("TicketList", input_json)?; let state = params.state.unwrap_or(TicketListStateParam::All); @@ -707,7 +707,7 @@ impl Tool for TicketShowTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketShowParams = parse_input("TicketShow", input_json)?; let query = id_or_query(params.id, params.query)?; @@ -743,7 +743,7 @@ impl Tool for TicketCommentTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketCommentParams = parse_input("TicketComment", input_json)?; let kind = match params.role { @@ -770,7 +770,7 @@ impl Tool for TicketReviewTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketReviewParams = parse_input("TicketReview", input_json)?; let result = match params.result { @@ -798,7 +798,7 @@ impl Tool for TicketIntakeReadyTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketIntakeReadyParams = parse_input("TicketIntakeReady", input_json)?; let from = TicketWorkflowState::Planning; @@ -837,7 +837,7 @@ impl Tool for TicketWorkflowStateTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketWorkflowStateParams = parse_input("TicketWorkflowState", input_json)?; let from = params.from.into_state(); @@ -876,7 +876,7 @@ impl Tool for TicketCloseTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketCloseParams = parse_input("TicketClose", input_json)?; self.backend @@ -897,7 +897,7 @@ impl Tool for TicketRelationRecordTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketRelationRecordParams = parse_input("TicketRelationRecord", input_json)?; let relation = NewTicketRelation { @@ -925,7 +925,7 @@ impl Tool for TicketRelationQueryTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketRelationQueryParams = parse_input("TicketRelationQuery", input_json)?; let limit = bounded(params.limit, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT); @@ -963,7 +963,7 @@ impl Tool for TicketOrchestrationPlanRecordTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketOrchestrationPlanRecordParams = parse_input("TicketOrchestrationPlanRecord", input_json)?; @@ -999,7 +999,7 @@ impl Tool for TicketOrchestrationPlanQueryTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketOrchestrationPlanQueryParams = parse_input("TicketOrchestrationPlanQuery", input_json)?; @@ -1040,7 +1040,7 @@ impl Tool for TicketDoctorTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: TicketDoctorParams = parse_input("TicketDoctor", input_json)?; let limit = bounded(params.limit, DEFAULT_DIAGNOSTIC_LIMIT, MAX_DIAGNOSTIC_LIMIT); diff --git a/crates/tools/Cargo.toml b/crates/tools/Cargo.toml index 83d6e4e2..d3bd277c 100644 --- a/crates/tools/Cargo.toml +++ b/crates/tools/Cargo.toml @@ -12,7 +12,7 @@ grep-regex = "0.1.14" grep-searcher = "0.1.16" ignore = "0.4.25" html5ever = "0.26" -llm-worker = { workspace = true } +llm-engine = { workspace = true } manifest = { workspace = true } secrets = { workspace = true } markup5ever_rcdom = "0.2" diff --git a/crates/tools/README.md b/crates/tools/README.md index 46c64c0e..82f8ce0c 100644 --- a/crates/tools/README.md +++ b/crates/tools/README.md @@ -16,7 +16,7 @@ Owns: Does not own: - manifest permission policy definition (`manifest`) -- Worker tool-loop semantics (`llm-worker`) +- Engine tool-loop semantics (`llm-engine`) - Pod lifecycle decisions (`pod`) - UI presentation (`tui`) diff --git a/crates/tools/src/bash.rs b/crates/tools/src/bash.rs index 95bc3517..6bd6f228 100644 --- a/crates/tools/src/bash.rs +++ b/crates/tools/src/bash.rs @@ -11,7 +11,7 @@ //! returned inline and the file is cleaned up. When it is longer the //! full output is left on disk and only the **last 80 lines** are //! returned, prefixed with the saved file's path. This sidesteps the -//! Worker's blanket `ToolOutputLimits` (default 64 KiB), which would +//! Engine's blanket `ToolOutputLimits` (default 64 KiB), which would //! otherwise drop the *tail* of the output — usually the most useful //! part (errors, exit messages, summary). The saved file lives under //! a caller-supplied directory that the parent has added to the @@ -28,7 +28,7 @@ use std::sync::Arc; use std::time::Duration; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use tokio::process::Command; @@ -56,7 +56,7 @@ const TAIL_LINES: usize = 80; /// Inline-return budget. Outputs at or below this are returned in full; /// above it triggers the spill-to-file path. Sized to leave headroom under -/// the Worker's 64 KiB default `ToolOutputLimits` cap so the inline path +/// the Engine's 64 KiB default `ToolOutputLimits` cap so the inline path /// reliably reaches the model intact. const INLINE_BYTE_BUDGET: usize = 12 * 1024; @@ -104,7 +104,7 @@ impl Tool for BashTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: BashParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid Bash input: {e}")))?; @@ -222,7 +222,7 @@ impl Tool for BashTool { } // Inline if the whole output fits in our tail-read window AND is - // small enough to ride under the Worker's default cap. + // small enough to ride under the Engine's default cap. let line_count = tail_text.lines().count(); let fully_loaded = total_bytes <= tail_bytes.len(); let fits_inline = diff --git a/crates/tools/src/edit.rs b/crates/tools/src/edit.rs index 13ede1b3..4c92a6b1 100644 --- a/crates/tools/src/edit.rs +++ b/crates/tools/src/edit.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use crate::error::ToolsError; @@ -39,7 +39,7 @@ impl Tool for EditTool { async fn execute( &self, input_json: &str, - ctx: llm_worker::tool::ToolExecutionContext, + ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: EditParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid Edit input: {e}")))?; diff --git a/crates/tools/src/error.rs b/crates/tools/src/error.rs index a4c4174b..b35c1dc9 100644 --- a/crates/tools/src/error.rs +++ b/crates/tools/src/error.rs @@ -2,11 +2,11 @@ //! //! `ToolsError` is the crate-level error returned by `ScopedFs` and each //! builtin tool's internal logic. Tool `execute()` impls convert it to -//! [`llm_worker::tool::ToolError`] via the `From` impl defined here. +//! [`llm_engine::tool::ToolError`] via the `From` impl defined here. use std::path::PathBuf; -use llm_worker::tool::ToolError; +use llm_engine::tool::ToolError; #[derive(Debug, thiserror::Error)] pub enum ToolsError { diff --git a/crates/tools/src/glob.rs b/crates/tools/src/glob.rs index 0cd47537..782cddc8 100644 --- a/crates/tools/src/glob.rs +++ b/crates/tools/src/glob.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use std::time::SystemTime; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use manifest::Scope; use serde::Deserialize; @@ -38,7 +38,7 @@ impl Tool for GlobTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: GlobParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid Glob input: {e}")))?; diff --git a/crates/tools/src/grep.rs b/crates/tools/src/grep.rs index 35672dbb..f7ccd2ba 100644 --- a/crates/tools/src/grep.rs +++ b/crates/tools/src/grep.rs @@ -10,7 +10,7 @@ use grep_searcher::{BinaryDetection, Searcher, SearcherBuilder, Sink, SinkContex use ignore::WalkBuilder; use ignore::overrides::OverrideBuilder; use ignore::types::TypesBuilder; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use manifest::Scope; use serde::Deserialize; @@ -85,7 +85,7 @@ impl Tool for GrepTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: GrepParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid Grep input: {e}")))?; diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs index 4a55feb8..f253f678 100644 --- a/crates/tools/src/lib.rs +++ b/crates/tools/src/lib.rs @@ -1,7 +1,7 @@ //! Built-in tools for the Yoi LLM agent. //! //! Implements Read / Write / Edit / Glob / Grep / Bash on top of the -//! `llm-worker` `Tool` infrastructure. Filesystem access is mediated by +//! `llm-engine` `Tool` infrastructure. Filesystem access is mediated by //! two orthogonal concerns: //! //! - [`ScopedFs`] — Pod-process lifetime, expresses the write-block @@ -12,7 +12,7 @@ //! Recreated fresh on each Pod start (including resume). //! //! The Pod layer owns both instances and passes them to -//! [`core_builtin_tools`] when registering tools on a `Worker`. +//! [`core_builtin_tools`] when registering tools on a `Engine`. //! //! `Bash` is the lone exception — its child processes bypass `ScopedFs` //! entirely. Safety for arbitrary command execution is delegated to the @@ -57,7 +57,7 @@ pub fn core_builtin_tools( fs: ScopedFs, tracker: Tracker, bash_output_dir: std::path::PathBuf, -) -> Vec { +) -> Vec { vec![ read_tool(fs.clone(), tracker.clone()), write_tool(fs.clone(), tracker.clone()), @@ -70,7 +70,7 @@ pub fn core_builtin_tools( pub fn web_builtin_tools( web_config: Option, -) -> Vec { +) -> Vec { vec![ web_search_tool(web::WebTools::new(web_config.clone())), web_fetch_tool(web::WebTools::new(web_config)), diff --git a/crates/tools/src/read.rs b/crates/tools/src/read.rs index 34b8fbdf..6f53cc78 100644 --- a/crates/tools/src/read.rs +++ b/crates/tools/src/read.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use crate::scoped_fs::ScopedFs; @@ -39,7 +39,7 @@ impl Tool for ReadTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: ReadParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid Read input: {e}")))?; diff --git a/crates/tools/src/tracker.rs b/crates/tools/src/tracker.rs index 867b0423..ef48bd6a 100644 --- a/crates/tools/src/tracker.rs +++ b/crates/tools/src/tracker.rs @@ -40,7 +40,7 @@ use std::collections::{HashMap, VecDeque}; use std::path::{Component, Path, PathBuf}; -use llm_worker::tool::ToolExecutionContext; +use llm_engine::tool::ToolExecutionContext; use std::sync::{Arc, Mutex}; use sha2::{Digest, Sha256}; @@ -142,7 +142,7 @@ impl Tracker { /// Acquire the per-target-file mutation guard shared by `Write` and `Edit`. /// /// The guard is keyed by canonical target path where possible so equivalent - /// paths serialize through the same lock. Worker still executes tool calls in + /// paths serialize through the same lock. Engine still executes tool calls in /// parallel; this only gates the critical filesystem mutation section for /// builtin file mutation tools. pub(crate) async fn acquire_mutation( diff --git a/crates/tools/src/web.rs b/crates/tools/src/web.rs index 34835aeb..3634db26 100644 --- a/crates/tools/src/web.rs +++ b/crates/tools/src/web.rs @@ -6,7 +6,7 @@ use std::time::Duration; use async_trait::async_trait; use html5ever::tendril::TendrilSink; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use manifest::{WebConfig, WebFetchConfig, WebSearchConfig, WebSearchProvider}; use markup5ever_rcdom::{Handle, NodeData, RcDom}; use reqwest::header::{CONTENT_LENGTH, CONTENT_TYPE, HeaderMap, LOCATION}; @@ -149,7 +149,7 @@ impl Tool for WebSearchTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: WebSearchInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid WebSearch input: {e}")))?; @@ -200,7 +200,7 @@ impl Tool for WebFetchTool { async fn execute( &self, input_json: &str, - _ctx: llm_worker::tool::ToolExecutionContext, + _ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let input: WebFetchInput = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid WebFetch input: {e}")))?; diff --git a/crates/tools/src/write.rs b/crates/tools/src/write.rs index 5df7d335..233656d1 100644 --- a/crates/tools/src/write.rs +++ b/crates/tools/src/write.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use std::sync::Arc; use async_trait::async_trait; -use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; +use llm_engine::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput}; use serde::Deserialize; use crate::scoped_fs::ScopedFs; @@ -33,7 +33,7 @@ impl Tool for WriteTool { async fn execute( &self, input_json: &str, - ctx: llm_worker::tool::ToolExecutionContext, + ctx: llm_engine::tool::ToolExecutionContext, ) -> Result { let params: WriteParams = serde_json::from_str(input_json) .map_err(|e| ToolError::InvalidArgument(format!("invalid Write input: {e}")))?; @@ -237,7 +237,7 @@ mod tests { #[tokio::test] async fn write_then_edit_same_file_same_batch_uses_call_order() { use crate::edit::edit_tool; - use llm_worker::tool::ToolExecutionContext; + use llm_engine::tool::ToolExecutionContext; let (dir, fs, tracker) = setup(); let file = dir.path().join("ordered.txt"); @@ -272,7 +272,7 @@ mod tests { #[tokio::test] async fn failed_same_file_mutation_releases_guard_for_followup() { use crate::edit::edit_tool; - use llm_worker::tool::ToolExecutionContext; + use llm_engine::tool::ToolExecutionContext; let (dir, fs, tracker) = setup(); let file = dir.path().join("release.txt"); diff --git a/crates/tools/tests/edge_cases.rs b/crates/tools/tests/edge_cases.rs index a3014ca2..2203252d 100644 --- a/crates/tools/tests/edge_cases.rs +++ b/crates/tools/tests/edge_cases.rs @@ -2,14 +2,14 @@ use std::sync::Arc; -use llm_worker::tool::{Tool, ToolDefinition}; +use llm_engine::tool::{Tool, ToolDefinition}; use manifest::{Permission, Scope, ScopeConfig, ScopeRule}; use serde_json::json; use tempfile::TempDir; use tools::{ScopedFs, Tracker, core_builtin_tools}; struct Registry { - entries: Vec<(llm_worker::tool::ToolMeta, Arc)>, + entries: Vec<(llm_engine::tool::ToolMeta, Arc)>, } impl Registry { diff --git a/crates/tools/tests/integration.rs b/crates/tools/tests/integration.rs index 3fd74620..7c4eeddb 100644 --- a/crates/tools/tests/integration.rs +++ b/crates/tools/tests/integration.rs @@ -1,13 +1,13 @@ //! Cross-tool integration tests exercising `core_builtin_tools()` end-to-end. //! //! `ToolServerHandle::register_tool` / `flush_pending` are `pub(crate)` in -//! llm-worker, so from here we exercise the factories directly — the same +//! llm-engine, so from here we exercise the factories directly — the same //! code path that `flush_pending()` runs at production time. use std::path::Path; use std::sync::Arc; -use llm_worker::tool::{Tool, ToolDefinition, ToolMeta}; +use llm_engine::tool::{Tool, ToolDefinition, ToolMeta}; use manifest::{Permission, Scope, ScopeConfig, ScopeRule}; use serde_json::json; use tempfile::TempDir; @@ -60,13 +60,13 @@ fn setup() -> (TempDir, TempDir, Registry) { (dir, spill, reg) } -async fn call(tool: &Arc, input: serde_json::Value) -> llm_worker::tool::ToolOutput { +async fn call(tool: &Arc, input: serde_json::Value) -> llm_engine::tool::ToolOutput { tool.execute(&input.to_string(), Default::default()) .await .expect("tool execution failed") } -async fn call_err(tool: &Arc, input: serde_json::Value) -> llm_worker::tool::ToolError { +async fn call_err(tool: &Arc, input: serde_json::Value) -> llm_engine::tool::ToolError { tool.execute(&input.to_string(), Default::default()) .await .expect_err("expected error") diff --git a/crates/tui/Cargo.toml b/crates/tui/Cargo.toml index b035e62d..1389200f 100644 --- a/crates/tui/Cargo.toml +++ b/crates/tui/Cargo.toml @@ -29,7 +29,7 @@ ticket = { workspace = true } serde = { workspace = true, features = ["derive"] } minijinja = "2.19.0" pulldown-cmark = { version = "0.13.3", default-features = false } -llm-worker.workspace = true +llm-engine.workspace = true [dev-dependencies] tempfile = { workspace = true } diff --git a/crates/tui/src/app.rs b/crates/tui/src/app.rs index 87f77ffa..73de25cb 100644 --- a/crates/tui/src/app.rs +++ b/crates/tui/src/app.rs @@ -2051,7 +2051,7 @@ impl App { match entry { session_store::LogEntry::SegmentStart { history, .. } => { for logged in history { - let item: llm_worker::Item = logged.into(); + let item: llm_engine::Item = logged.into(); let item_value = serde_json::to_value(&item).expect("Item is Serialize"); self.push_history_item(&item_value); } @@ -2067,7 +2067,7 @@ impl App { } session_store::LogEntry::AssistantItem { item, .. } | session_store::LogEntry::ToolResult { item, .. } => { - let it: llm_worker::Item = item.into(); + let it: llm_engine::Item = item.into(); let item_value = serde_json::to_value(&it).expect("Item is Serialize"); self.push_history_item(&item_value); } @@ -2231,7 +2231,7 @@ fn rollback_input_preview(text: &str) -> String { pub fn alert_source_label(source: AlertSource) -> &'static str { match source { AlertSource::Pod => "pod", - AlertSource::Worker => "worker", + AlertSource::Engine => "engine", AlertSource::Compactor => "compactor", AlertSource::AgentsMd => "AGENTS.md", } @@ -2780,7 +2780,7 @@ mod completion_flow_tests { is_dir: true, }, CompletionEntry { - value: "crates/llm-worker".into(), + value: "crates/llm-engine".into(), is_dir: true, }, ]; @@ -2933,7 +2933,7 @@ mod completion_flow_tests { ts: session_store::segment_log::now_millis(), session_id: uuid::Uuid::nil(), system_prompt: None, - config: llm_worker::llm_client::RequestConfig::default(), + config: llm_engine::llm_client::RequestConfig::default(), history: vec![], forked_from: None, compacted_from: None, @@ -3192,7 +3192,7 @@ mod completion_flow_tests { system_prompt: None, config: Default::default(), history: vec![session_store::LoggedItem::from( - &llm_worker::Item::system_message("[File: src/main.rs]\nfn main() {}"), + &llm_engine::Item::system_message("[File: src/main.rs]\nfn main() {}"), )], forked_from: None, compacted_from: None, diff --git a/crates/tui/src/pod_list.rs b/crates/tui/src/pod_list.rs index 838a5497..44a8a42a 100644 --- a/crates/tui/src/pod_list.rs +++ b/crates/tui/src/pod_list.rs @@ -558,7 +558,7 @@ mod tests { use super::*; use std::sync::Arc; - use llm_worker::llm_client::types::RequestConfig; + use llm_engine::llm_client::types::RequestConfig; use pod_store::FsPodStore; use pod_store::{PodActiveSegmentRef, PodMetadataStore}; use protocol::stream::JsonLineWriter; diff --git a/crates/yoi/README.md b/crates/yoi/README.md index b9678715..0c0ae8a4 100644 --- a/crates/yoi/README.md +++ b/crates/yoi/README.md @@ -17,7 +17,7 @@ Does not own: - Pod runtime internals (`pod`) - socket client mechanics (`client`) -- model turn orchestration (`llm-worker`) +- model turn orchestration (`llm-engine`) - TUI rendering/runtime implementation (`tui`) ## Design notes diff --git a/docs/design/context-history.md b/docs/design/context-history.md index 20941971..17a44088 100644 --- a/docs/design/context-history.md +++ b/docs/design/context-history.md @@ -28,7 +28,7 @@ Forbidden examples: - Rewriting old messages to include new facts. - Letting UI/controller-only state become model-visible without a committed record. -If new information should affect the model, append it to history and commit it. `history.json` / session persistence follows from the Worker history path. +If new information should affect the model, append it to history and commit it. `history.json` / session persistence follows from the Engine history path. ## Prompt cache implications diff --git a/docs/design/overview.md b/docs/design/overview.md index 161b520b..e4ca0d48 100644 --- a/docs/design/overview.md +++ b/docs/design/overview.md @@ -7,8 +7,8 @@ That rule shapes the crate split. The runtime can restart, attach, compact, or d ## Core layers - `yoi` owns the product CLI and top-level command shape. It is the façade that wires profile selection, memory linting, and normal TUI launch. -- `pod` turns a `Worker` into a named runtime entity with scope, session persistence, protocol handling, tools, and Pod metadata integration. -- `llm-worker` owns model-facing turns: history append, retries, continuation, pruning/compaction mechanics, tool loops, and provider-independent callbacks. +- `pod` turns a `Engine` into a named runtime entity with scope, session persistence, protocol handling, tools, and Pod metadata integration. +- `llm-engine` owns model-facing turns: history append, retries, continuation, pruning/compaction mechanics, tool loops, and provider-independent callbacks. - `session-store` owns replayable append-only conversation/session logs. - `pod-store` owns current Pod metadata keyed by Pod name. - `protocol` defines the socket message boundary between clients and Pods. @@ -21,9 +21,9 @@ That rule shapes the crate split. The runtime can restart, attach, compact, or d ## Why these boundaries exist -The Worker should not know process identity, Pod names, live sockets, spawned children, or UI state. It should know how to run an LLM turn over committed history and tools. +The Engine should not know process identity, Pod names, live sockets, spawned children, or UI state. It should know how to run an LLM turn over committed history and tools. -The Pod should not make provider-specific wire decisions. It coordinates runtime identity, persistence, scope, and protocol delivery around a Worker. +The Pod should not make provider-specific wire decisions. It coordinates runtime identity, persistence, scope, and protocol delivery around a Engine. The TUI should not be an alternate source of truth. It may queue local input, show optimistic affordances, and render snapshots, but durable state comes from Pod/session records. diff --git a/docs/design/plugin-component-model.md b/docs/design/plugin-component-model.md index 11f7f062..eb492650 100644 --- a/docs/design/plugin-component-model.md +++ b/docs/design/plugin-component-model.md @@ -68,7 +68,7 @@ Adopting the Component Model must not change Yoi's authority model: - Explicit enablement is required before any Tool surface is registered. - Plugin grants are required before runtime execution and before `https` / `fs` / future host API calls. - Component imports are not authority by themselves; host-side grant checks remain authoritative. -- Tool calls and Tool results continue through the ordinary ToolRegistry and Worker history path. +- Tool calls and Tool results continue through the ordinary ToolRegistry and Engine history path. - No hidden context injection is introduced by component imports, resources, prompts, or SDK helpers. - Plugin SDKs and templates are authoring aids, not trust boundaries. @@ -120,7 +120,7 @@ The component runtime uses `wasmtime::component` and expects the exported world `yoi:plugin/tool@1.0.0` with a `call(tool-name: string, input-json: string) -> string` export. The returned string is the normal ToolOutput JSON, so registration and execution still flow through the existing ToolRegistry and -Worker Tool-result history path. +Engine Tool-result history path. Host imports are stable names under `yoi:host/*@1.0.0`; the repository WIT files live in `resources/plugin/wit/`. Importing `yoi:host/request@1.0.0` or @@ -164,7 +164,7 @@ authority model. Important boundaries: - Tool calls still enter through `ToolRegistry` and return ordinary `ToolOutput` - that is visible in the Worker history path. + that is visible in the Engine history path. - Service and Ingress grants are separate from Tool grants. Sharing an instance does not authorize a surface that lacks its own `surface.*` and per-surface permission/grant. diff --git a/docs/design/plugin-packages.md b/docs/design/plugin-packages.md index 74852697..0729b5cf 100644 --- a/docs/design/plugin-packages.md +++ b/docs/design/plugin-packages.md @@ -173,7 +173,7 @@ Diagnostics should be safe, bounded, and attributable: ## Runtime notes -Declarative hooks are data contributions. Loading a declarative hook still requires explicit package enablement. Hook text should enter the system through the normal Hook/Worker paths, preserving the rule that model-affecting inputs are committed to history before they affect context when applicable. +Declarative hooks are data contributions. Loading a declarative hook still requires explicit package enablement. Hook text should enter the system through the normal Hook/Engine paths, preserving the rule that model-affecting inputs are committed to history before they affect context when applicable. WASM packages should initialize only from the digest-keyed cache after enablement and grant resolution. The host should use a narrow ABI, bounded memory, fuel/time limits, bounded output, and explicit host functions. A WASM module must not inherit filesystem, network, tool, secret, process, or MCP authority from the package store path. diff --git a/docs/design/provider-model-boundary.md b/docs/design/provider-model-boundary.md index 756c6ec7..c85adc8b 100644 --- a/docs/design/provider-model-boundary.md +++ b/docs/design/provider-model-boundary.md @@ -1,10 +1,10 @@ # Provider and model boundary -The Worker should be provider-independent. Provider-specific wire formats, auth mechanisms, model catalogs, reasoning knobs, and terminal error shapes belong below or beside it, not inside ordinary turn orchestration. +The Engine should be provider-independent. Provider-specific wire formats, auth mechanisms, model catalogs, reasoning knobs, and terminal error shapes belong below or beside it, not inside ordinary turn orchestration. -## Worker responsibility +## Engine responsibility -`llm-worker` owns turn lifecycle: +`llm-engine` owns turn lifecycle: - committed history append - tool loops @@ -42,4 +42,4 @@ Event trace sidecars are optional parsed lifecycle traces. They are not complete ## Why this boundary exists -Provider APIs drift. If provider details leak into Worker logic, every new model behavior risks changing core orchestration. Keeping the boundary explicit lets Yoi adapt provider integrations while preserving stable turn semantics. +Provider APIs drift. If provider details leak into Engine logic, every new model behavior risks changing core orchestration. Keeping the boundary explicit lets Yoi adapt provider integrations while preserving stable turn semantics. diff --git a/docs/development/plugin-development.md b/docs/development/plugin-development.md index 0e745dd7..dcc90f67 100644 --- a/docs/development/plugin-development.md +++ b/docs/development/plugin-development.md @@ -9,7 +9,7 @@ Yoi Plugins are intentionally explicit. The Plugin system is designed around the - Plugin grants must allow each surface and host API before registration or execution can use it; - Plugin code runs only through the configured sandbox runtime; - Plugin packages do not inherit Pod workspace filesystem, network, environment, or Ticket authority; -- Tool calls and Tool results use the ordinary Yoi Tool/Worker history path; +- Tool calls and Tool results use the ordinary Yoi Tool/Engine history path; - Plugin metadata, output, and diagnostics are untrusted unless Yoi host policy says otherwise. ## Design intent diff --git a/package.nix b/package.nix index 17891ce9..cfbef52b 100644 --- a/package.nix +++ b/package.nix @@ -43,7 +43,7 @@ rustPlatform.buildRustPackage rec { filter = sourceFilter; }; - cargoHash = "sha256-kO1hvSYAVOVOIubP0Tm2Gpx2EWK7jwUKe30I8qTTU00="; + cargoHash = "sha256-GnzrlfCbLv09XH8J3cTeaOXl+tcelfQVtSG7aZVS82E="; depsExtraArgs = { # Older fetchCargoVendor utilities used crates.io's API download endpoint, From 50e2754e5e60252164484aa2dfef4803b5a13b29 Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 25 Jun 2026 22:47:33 +0900 Subject: [PATCH 5/7] ticket: record llm engine implementation report --- .yoi/tickets/00001KVZD10ED/item.md | 2 +- .yoi/tickets/00001KVZD10ED/thread.md | 56 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/.yoi/tickets/00001KVZD10ED/item.md b/.yoi/tickets/00001KVZD10ED/item.md index 0dea36cd..190b1a5f 100644 --- a/.yoi/tickets/00001KVZD10ED/item.md +++ b/.yoi/tickets/00001KVZD10ED/item.md @@ -2,7 +2,7 @@ title: 'llm-worker crateをllm-engineへ改名する' state: 'inprogress' created_at: '2026-06-25T12:45:38Z' -updated_at: '2026-06-25T13:28:20Z' +updated_at: '2026-06-25T13:47:26Z' assignee: null queued_by: 'workspace-panel' queued_at: '2026-06-25T13:24:26Z' diff --git a/.yoi/tickets/00001KVZD10ED/thread.md b/.yoi/tickets/00001KVZD10ED/thread.md index 8b7c30c1..9f9c8581 100644 --- a/.yoi/tickets/00001KVZD10ED/thread.md +++ b/.yoi/tickets/00001KVZD10ED/thread.md @@ -134,3 +134,59 @@ Implementation orchestration update: - Coder には root/original workspace と orchestration worktree で read/write/validation/git operation を行わないよう明示した。 --- + + + +## Implementation report + +Implementation report: + +対象 Ticket: +- `00001KVZD10ED` — `llm-worker crateをllm-engineへ改名する` + +実装概要: +- `crates/llm-worker` → `crates/llm-engine` +- `crates/llm-worker-macros` → `crates/llm-engine-macros` +- Cargo package / workspace dependency 名を `llm-engine` / `llm-engine-macros` へ更新。 +- Rust import path を `llm_engine` / `llm_engine_macros` へ更新。 +- turn-engine API を rename。 + - `Worker` → `Engine` + - `WorkerConfig` → `EngineConfig` + - `WorkerError` → `EngineError` + - `WorkerResult` → `EngineResult` + - `WorkerState` → `EngineState` + - `RunOutput` → `EngineRunOutput` +- `pod` 側の engine 保持 API / error / alert source 等も rename fallout として更新。 +- docs / tests / examples / Nix / `Cargo.lock` / `package.nix` hash を更新。 +- 旧 crate directory は削除済みで、互換 alias は追加していない。 + +Commit: +- `292fc4ea refactor: rename llm worker crate to engine` + +Validation: +- `cargo test -p llm-engine`: success +- `cargo test -p pod`: success + - 既知 caveat の prompt guidance snapshot failure は今回発生しなかった。 +- `cargo check -p yoi`: success +- `git diff --check`: success +- `nix build .#yoi --no-link`: success + +Grep evidence: +- `.yoi/tickets/**` と `docs/report/**` を除外した active tree で以下の旧 active references は 0 件。 + - `llm-worker` + - `llm_worker` + - `llm-worker-macros` + - `llm_worker_macros` +- `crates/llm-engine` / `crates/llm-engine-macros` 内の旧 public Worker API 名も 0 件。 + - `\bWorker\b` + - `WorkerConfig` + - `WorkerError` + - `WorkerResult` + - `WorkerState` +- historical `.yoi/tickets` / `docs/report` 内には旧語が残る。count: 786。これは Ticket 本文・過去 report 類の履歴文脈として意図的に残している。 + +Residual risks / notes: +- 互換 alias は入れていないため、外部未追跡コードが `llm-worker` / `llm_worker::Worker` を直接参照している場合は破壊的変更になる。ただし Ticket の binding invariant 通り。 +- merge / Ticket close / worktree cleanup は未実施。 + +--- From 4d8e022465889859d1225c9cc344c17beb8d0ff0 Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 25 Jun 2026 22:54:25 +0900 Subject: [PATCH 6/7] ticket: approve llm engine rename --- .yoi/tickets/00001KVZD10ED/item.md | 2 +- .yoi/tickets/00001KVZD10ED/thread.md | 49 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/.yoi/tickets/00001KVZD10ED/item.md b/.yoi/tickets/00001KVZD10ED/item.md index 190b1a5f..3012c279 100644 --- a/.yoi/tickets/00001KVZD10ED/item.md +++ b/.yoi/tickets/00001KVZD10ED/item.md @@ -2,7 +2,7 @@ title: 'llm-worker crateをllm-engineへ改名する' state: 'inprogress' created_at: '2026-06-25T12:45:38Z' -updated_at: '2026-06-25T13:47:26Z' +updated_at: '2026-06-25T13:54:15Z' assignee: null queued_by: 'workspace-panel' queued_at: '2026-06-25T13:24:26Z' diff --git a/.yoi/tickets/00001KVZD10ED/thread.md b/.yoi/tickets/00001KVZD10ED/thread.md index 9f9c8581..b6a63a00 100644 --- a/.yoi/tickets/00001KVZD10ED/thread.md +++ b/.yoi/tickets/00001KVZD10ED/thread.md @@ -190,3 +190,52 @@ Residual risks / notes: - merge / Ticket close / worktree cleanup は未実施。 --- + + + +## Review: approve + +Review result: approve + +確認結果、Ticket `00001KVZD10ED` の IntentPacket / acceptance criteria に対してブロッカーは見つかりませんでした。 + +Read-only 確認: +- 対象 worktree / branch / commit: + - `work/00001KVZD10ED-llm-engine-rename` + - HEAD `292fc4ea` + - base `22598710` は ancestor。 +- Ticket 記録: + - `thread.md` の IntentPacket / acceptance criteria / reviewer focus を確認。 + - 要件は `llm-worker` → `llm-engine`、public turn-engine API を `Worker` 系から `Engine` 系へ rename、互換 alias なし、責務移動なし。 +- crate / directory: + - `crates/llm-engine`, `crates/llm-engine-macros` が存在。 + - `crates/llm-worker`, `crates/llm-worker-macros` は存在しない。 +- Cargo / Nix: + - root `Cargo.toml` の members/default-members/workspace deps が `llm-engine` / `llm-engine-macros`。 + - `crates/pod/Cargo.toml` 等の依存も `llm-engine`。 + - `Cargo.lock` は旧 package 名から新 package 名へ置換済み。 + - `package.nix` の `cargoHash` 更新を確認。 +- public API: + - `crates/llm-engine/src/lib.rs` は `Engine`, `EngineConfig`, `EngineError`, `EngineResult`, `EngineRunOutput` を export。 + - `WorkerConfig` / `WorkerError` / `WorkerResult` / `WorkerState` / bare `RunOutput` は active tree で検出されず。 + - `llm-engine` / `llm-engine-macros` 内に `pub type Worker` 等の互換 alias は見つからず。 +- stale reference: + - `.yoi/tickets/**` と `docs/report/**` を除いた tracked active tree で `llm-worker`, `llm_worker`, `llm-worker-macros`, `llm_worker_macros` は検出されず。 +- behavior / responsibility risk: + - `crates/llm-worker/src/worker.rs` → `crates/llm-engine/src/engine.rs` は正規化比較で import order / formatting 程度の差分に収まっていることを確認。 + - `crates/llm-engine/README.md` に Pod names / sockets / process lifecycle / scope delegation / durable Pod state を持たない境界が明記されており、Runtime/Worker identity や socket/session authority の責務移動は見当たらない。 +- whitespace: + - `git diff --check 22598710..HEAD`: success。 + +未再実行: +- `cargo test -p llm-engine` +- `cargo test -p pod` +- `cargo check -p yoi` +- `nix build .#yoi --no-link` + +上記は reviewer の read-only/no-write 条件を優先して再実行していない。coder 報告では成功済み。 + +Non-blocking note: +- `pod` 側には local variable や既存 runtime/manifest 文脈としての `worker` 語が残っているが、今回の acceptance 対象である old crate/import/API 名や `llm_engine::Worker` 互換 alias ではないため問題なし。 + +--- From 6ab0d64fcbad64805c0de168485c35c8d16ac475 Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 25 Jun 2026 22:57:39 +0900 Subject: [PATCH 7/7] ticket: mark llm engine rename done --- .yoi/tickets/00001KVZD10ED/item.md | 4 +- .yoi/tickets/00001KVZD10ED/thread.md | 76 ++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/.yoi/tickets/00001KVZD10ED/item.md b/.yoi/tickets/00001KVZD10ED/item.md index 3012c279..cf33d658 100644 --- a/.yoi/tickets/00001KVZD10ED/item.md +++ b/.yoi/tickets/00001KVZD10ED/item.md @@ -1,8 +1,8 @@ --- title: 'llm-worker crateをllm-engineへ改名する' -state: 'inprogress' +state: 'done' created_at: '2026-06-25T12:45:38Z' -updated_at: '2026-06-25T13:54:15Z' +updated_at: '2026-06-25T13:57:29Z' assignee: null queued_by: 'workspace-panel' queued_at: '2026-06-25T13:24:26Z' diff --git a/.yoi/tickets/00001KVZD10ED/thread.md b/.yoi/tickets/00001KVZD10ED/thread.md index b6a63a00..6cd640aa 100644 --- a/.yoi/tickets/00001KVZD10ED/thread.md +++ b/.yoi/tickets/00001KVZD10ED/thread.md @@ -239,3 +239,79 @@ Non-blocking note: - `pod` 側には local variable や既存 runtime/manifest 文脈としての `worker` 語が残っているが、今回の acceptance 対象である old crate/import/API 名や `llm_engine::Worker` 互換 alias ではないため問題なし。 --- + + + +## Implementation report + +Integration outcome: + +- Coder `yoi-coder-00001KVZD10ED-llm-engine` が implementation branch `work/00001KVZD10ED-llm-engine-rename` に実装を commit した。 + - implementation commit: `292fc4ea refactor: rename llm worker crate to engine` +- Reviewer `yoi-reviewer-00001KVZD10ED-llm-engine` は read-only review で `approve`。old crate directories removal、Cargo/Nix consistency、public Engine API、old active references なし、compatibility alias なし、behavior/responsibility movement なしを確認した。 +- Orchestrator worktree `/home/hare/Projects/yoi/.worktree/orchestration` で branch `work/00001KVZD10ED-llm-engine-rename` を merge 済み。 + - merge commit: `254ecccb merge: 00001KVZD10ED llm engine rename` + +Implemented behavior: +- `crates/llm-worker` -> `crates/llm-engine` +- `crates/llm-worker-macros` -> `crates/llm-engine-macros` +- Cargo package/dependency/import path を `llm-engine` / `llm_engine`, `llm-engine-macros` / `llm_engine_macros` に更新。 +- Public turn-engine API を Engine 系へ rename。 + - `Worker` -> `Engine` + - `WorkerConfig` -> `EngineConfig` + - `WorkerError` -> `EngineError` + - `WorkerResult` -> `EngineResult` + - `WorkerState` -> `EngineState` + - `RunOutput` -> `EngineRunOutput` +- `pod`, `manifest`, docs, examples, tests, Nix, `Cargo.lock`, `package.nix` hash を更新。 +- old crate directories は削除済み。compatibility alias は追加していない。 + +Validation in Orchestrator worktree: +- `cargo test -p llm-engine`: success +- `cargo test -p pod`: success +- `cargo check -p yoi`: success +- active old reference grep excluding `.yoi/tickets/**` and `docs/report/**`: success, none found for: + - `llm-worker` + - `llm_worker` + - `llm-worker-macros` + - `llm_worker_macros` +- `crates/llm-engine` / `crates/llm-engine-macros` old public Worker API grep: success, none found for: + - `\bWorker\b` + - `WorkerConfig` + - `WorkerError` + - `WorkerResult` + - `WorkerState` +- `git diff --check`: success +- `nix build .#yoi --no-link`: success + +Notes: +- Historical `.yoi/tickets/**` and `docs/report/**` references to old names remain as durable history/report context and are not active API/docs guidance. +- Unlike recent Plugin full `cargo test -p pod` runs, this validation passed `cargo test -p pod` fully. + +Next action: +- Mark Ticket done after this integration/validation evidence. +- Then stop related child Pods and remove only the child implementation worktree/branch. + +--- + + + +## State changed + +Implementation is merged into the orchestration branch and validated. + +Evidence: +- merge commit: `254ecccb merge: 00001KVZD10ED llm engine rename` +- reviewer result: approve +- validation in `/home/hare/Projects/yoi/.worktree/orchestration` succeeded: + - `cargo test -p llm-engine` + - `cargo test -p pod` + - `cargo check -p yoi` + - active old reference grep excluding `.yoi/tickets/**` and `docs/report/**` + - old public Worker API grep in `crates/llm-engine` / `crates/llm-engine-macros` + - `git diff --check` + - `nix build .#yoi --no-link` + +Closure is not performed here; this state records implementation completion after merge/validation. + +---