# Todo 49 Tool Mode UI and Session Restore Plan **Status:** done ## Goal Make invocation mode and batch configuration visible/configurable in the debug UI, and restore a persisted direct-mode conversation with a provider-valid assistant/tool transcript. ## Observe / Update - UI request and workspace/session snapshots preserve invocation mode, parallelism, and timeout configuration. - Direct-mode protocol history is persisted and restored provider-validly; follow-up Todos 49.1-49.3 closed atomicity, legacy repair, migration, and asynchronous replay races. - Final verification after follow-ups: `388 passed`, `node --check` and `git diff --check` pass; one pre-existing Starlette deprecation warning remains. ## UI - Add a mode selector with: - `Dual Agent — fast reply + EventAgent` (default); - `ChatAgent Tools — native provider tools`. - Add concise mode help/applicability text: - dual mode: EventAgent model/system/extra-body may be used for missing argument fallback; - direct mode: ChatAgent proposes provider-resolved arguments, so EventAgent model prompt settings are inactive; enabled tools, loop budget, batch concurrency, and timeout still apply. - Add `max_parallel_events` and `batch_timeout_seconds` controls. - Include mode and new settings in WebSocket requests and workspace snapshots. - Restore them from workspace snapshots and persisted session config, with backward-compatible defaults. - When loading a session, fetch `/api/sessions/{id}` together with replay/audit/usage and apply its saved config to the UI. - New manually created sessions save the current workspace config. ## Persisted Transcript - Persist assistant `tool_calls` as JSON alongside role/content/name/tool-call ID. - Add a safe SQLite migration for existing databases. - Return `tool_calls` from the messages API and reconstruct `ChatMessage` values for Runtime session restoration. - On reusable session start with an existing `session_id`, load prior user/assistant/tool messages into active history after current system/pre-message context. - Persist direct-mode tool replies as messages; dual mode continues to persist only user-visible conversational history and summaries, not provider tool protocol messages. - Validate restored transcript ordering/IDs before the next provider call through existing client validation. ## Boundaries - Do not change result-policy behavior or batch scheduling. - Do not migrate historical rows into synthetic tool calls; old rows default to `[]`. - Do not expose internal tool messages as normal assistant chat bubbles beyond the existing tool replay style. - Comparison metrics remain Todo 50. ## Files - Modify: `src/agent_lab/infrastructure/sqlite_store.py` - Modify: `src/agent_lab/application/runtime.py` - Modify: `src/agent_lab/presentation/static/index.html` - Modify: `src/agent_lab/presentation/static/app.js` - Modify: `src/agent_lab/presentation/static/styles.css` only if mode help layout needs it - Modify: `tests/test_sqlite_store.py` - Modify: `tests/test_debug_runtime.py` - Modify: `tests/test_websocket_api.py` ## Requirement Execution Loop ### Plan 1. Add RED persistence/migration tests for assistant tool calls and tool replies. 2. Add RED Runtime reconnect tests proving the next direct provider request receives restored valid transcript. 3. Add RED static/request/snapshot/session-load tests for mode and batch config. 4. Implement the smallest schema migration, restore helper, and UI controls. 5. Run Python, JS syntax, full tests, and a local browser/static check if layout changes materially. ### Observe / Update Add `49.x` rows for review findings. Mark complete only when old sessions remain loadable and direct-mode restored transcripts pass provider validation. ## Verification - `UV_CACHE_DIR=.uv-cache uv run pytest tests/test_sqlite_store.py tests/test_debug_runtime.py tests/test_websocket_api.py -q` - `node --check src/agent_lab/presentation/static/app.js` - `UV_CACHE_DIR=.uv-cache uv run pytest` - `git diff --check`