|
@@ -0,0 +1,97 @@
|
|
|
|
|
+# Todo 13 Real Queue WebSocket Loop Plan
|
|
|
|
|
+
|
|
|
|
|
+**Status:** in_progress
|
|
|
|
|
+
|
|
|
|
|
+## Goal
|
|
|
|
|
+
|
|
|
|
|
+Make runtime queues real producer/consumer boundaries and let WebSocket run separate upstream and downstream tasks.
|
|
|
|
|
+
|
|
|
|
|
+## Why
|
|
|
|
|
+
|
|
|
|
|
+The original queue requirement names producers and consumers explicitly:
|
|
|
|
|
+
|
|
|
|
|
+- input queue: WebSocket upstream and EventAgent replies produce; ChatAgent consumes.
|
|
|
|
|
+- output queue: ChatAgent produces; WebSocket downstream consumes.
|
|
|
|
|
+- event queue: ChatAgent produces; EventAgent consumes.
|
|
|
|
|
+
|
|
|
|
|
+The current runtime logs queue put/get calls, but `DebugRuntime.run()` still produces and consumes output in one method, and WebSocket reads only one initial request.
|
|
|
|
|
+
|
|
|
|
|
+## Scope
|
|
|
|
|
+
|
|
|
|
|
+This todo covers:
|
|
|
|
|
+
|
|
|
|
|
+- Add a runtime session entrypoint that starts ChatAgent/EventAgent work and returns `RuntimeQueues`.
|
|
|
|
|
+- Keep `DebugRuntime.run()` as a compatibility wrapper for tests and scripts.
|
|
|
|
|
+- Add an EventAgent queue consumer task.
|
|
|
|
|
+- Preserve provider-valid history ordering when a user message arrives while a tool call is being handled.
|
|
|
|
|
+- Split the WebSocket handler into downstream output sending and upstream user-message receiving tasks.
|
|
|
|
|
+
|
|
|
|
|
+This todo does not cover:
|
|
|
|
|
+
|
|
|
|
|
+- Multi-session persistence.
|
|
|
|
|
+- Multiple simultaneous ChatAgent workers inside one debug session.
|
|
|
|
|
+- UI controls for sending a second user message during an active run.
|
|
|
|
|
+- Role validation and static asset packaging; those are separate todos.
|
|
|
|
|
+
|
|
|
|
|
+## Files
|
|
|
|
|
+
|
|
|
|
|
+- Modify: `src/agent_lab/application/queues.py`
|
|
|
|
|
+- Modify: `src/agent_lab/application/runtime.py`
|
|
|
|
|
+- Modify: `src/agent_lab/presentation/web.py`
|
|
|
|
|
+- Modify: `tests/test_debug_runtime.py`
|
|
|
|
|
+- Modify: `tests/test_websocket_api.py`
|
|
|
|
|
+- Do not modify unrelated UI styling.
|
|
|
|
|
+
|
|
|
|
|
+## Design
|
|
|
|
|
+
|
|
|
|
|
+Add `DebugRuntime.start(request) -> RuntimeQueues`. It should create or reuse `RuntimeQueues`, seed the initial user message into `queues.input`, start background runtime work, and return queues immediately.
|
|
|
|
|
+
|
|
|
|
|
+`DebugRuntime.run(request)` remains an async iterator by calling `start()` and then consuming `queues.output` until `done` or `error`.
|
|
|
|
|
+
|
|
|
|
|
+Runtime work should:
|
|
|
|
|
+
|
|
|
|
|
+- put output payloads onto `queues.output` only;
|
|
|
|
|
+- put ChatAgent events onto `queues.events`;
|
|
|
|
|
+- run an EventAgent worker that consumes `queues.events` and puts tool replies onto `queues.input`;
|
|
|
|
|
+- when waiting for a tool reply, buffer unrelated input messages so the next provider history is `assistant(tool_calls)` -> `tool` -> later `user`.
|
|
|
|
|
+
|
|
|
|
|
+WebSocket handling should:
|
|
|
|
|
+
|
|
|
|
|
+- read the first JSON payload as `DebugRunRequest`;
|
|
|
|
|
+- start the runtime session;
|
|
|
|
|
+- run a downstream task that consumes `queues.output` and sends JSON;
|
|
|
|
|
+- run an upstream task that accepts `{"type": "user_message", "content": "..."}` and puts `ChatMessage(role="user", content=...)` into `queues.input`.
|
|
|
|
|
+
|
|
|
|
|
+## Steps
|
|
|
|
|
+
|
|
|
|
|
+1. Add failing runtime tests:
|
|
|
|
|
+ - `DebugRuntime.start()` returns queues and output can be consumed directly.
|
|
|
|
|
+ - User input enqueued during an event handoff is preserved after the matching tool reply.
|
|
|
|
|
+2. Add a failing WebSocket test:
|
|
|
|
|
+ - send initial request;
|
|
|
|
|
+ - receive an event;
|
|
|
|
|
+ - send `{"type": "user_message", "content": "follow-up"}`;
|
|
|
|
|
+ - assert the second ChatAgent call receives provider-valid ordering.
|
|
|
|
|
+3. Refactor `DebugRuntime` to add `start()`, output queue consumption, EventAgent worker, and tool-reply wait logic.
|
|
|
|
|
+4. Refactor WebSocket presentation code into separate upstream/downstream tasks for runtimes that expose queue sessions.
|
|
|
|
|
+5. Run focused tests:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+uv run pytest tests/test_debug_runtime.py tests/test_websocket_api.py
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+6. Run the full suite:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+uv run pytest
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+7. Update `docs/plans/todos.md` and this plan with the result, then commit.
|
|
|
|
|
+
|
|
|
|
|
+## Verification
|
|
|
|
|
+
|
|
|
|
|
+Expected result:
|
|
|
|
|
+
|
|
|
|
|
+- Runtime tests prove output queue and event queue have separate consumers.
|
|
|
|
|
+- WebSocket tests prove upstream messages can enter the running input queue.
|
|
|
|
|
+- Full suite passes.
|