Quellcode durchsuchen

docs: close typed provider event todos

Problem: Todo 43 exposed legacy consumers and stale fixtures that required explicit 43.1 and 43.2 follow-up records.

Risk: StreamItem.event remains as a temporary compatibility constructor, but production consumers now reject the legacy kind.
zhenyu.hu vor 2 Wochen
Ursprung
Commit
e767911029

+ 9 - 1
docs/plans/todo-43-typed-provider-tool-calls.md

@@ -1,6 +1,14 @@
 # Todo 43 Typed Provider Tool Calls Plan
 
-**Status:** pending
+**Status:** done
+
+## Result
+
+- Added distinct `text_event` and `provider_tool_call` stream kinds.
+- Preserved provider IDs plus parsed/raw arguments and ordered multiple calls.
+- Added exactly-once flush behavior for providers that omit `finish_reason`.
+- Follow-up todos 43.1 and 43.2 repaired legacy consumers and removed production acceptance of the compatibility `event` kind.
+- Verified with focused regressions and the full suite (`82 passed`, one existing Starlette deprecation warning).
 
 ## Goal
 

+ 67 - 0
docs/plans/todo-43.1-typed-event-consumer-regression.md

@@ -0,0 +1,67 @@
+# Todo 43.1 Typed Event Consumer Regression Plan
+
+**Status:** done
+
+## Result
+
+- Runtime now consumes typed ChatAgent `text_event` output.
+- EventAgent now consumes typed provider `provider_tool_call` output.
+- Realistic fixtures exposed and fixed the legacy consumer mismatch.
+- Todo 43.2 completed strict source isolation and remaining fixture migration.
+
+## Goal
+
+Restore the existing dual-agent production paths after Todo 43 introduced typed stream kinds but legacy consumers and fixtures still listened for `kind="event"`.
+
+## Scope
+
+- Runtime consumes `text_event` from ChatAgent and preserves its name-only handoff behavior.
+- EventAgent argument generation consumes `provider_tool_call` and preserves provider-generated arguments.
+- Production-like test fixtures emit typed kinds instead of the legacy compatibility constructor.
+- Keep `StreamItem.event(...)` only as a temporary compatibility API for unrelated callers; new/updated production-path tests must not use it.
+- Do not add direct ChatAgent tool routing.
+
+## Files
+
+- Modify: `src/agent_lab/application/runtime.py`
+- Modify: `src/agent_lab/application/event_agent.py`
+- Modify: `tests/test_debug_runtime.py`
+- Modify: `tests/test_event_agent.py`
+
+## Plan
+
+### Plan
+
+1. Add or update tests so realistic ChatAgent fixtures emit `text_event` and EventAgent provider fixtures emit `provider_tool_call`.
+2. Verify tests fail because Runtime/EventAgent still consume only `event`.
+3. Change only the two legacy consumer checks to the correct typed kinds.
+4. Run focused and full regressions to prove no legacy path was silently lost.
+
+### Act
+
+- Update the minimum runtime fixture that drives text-event handoff to use `StreamItem.text_event(...)`.
+- Update EventAgent LLM argument fixtures to use `StreamItem.provider_tool_call(...)`.
+- Add explicit assertions that Runtime enqueues/executes the text event and EventAgent executes provider arguments without falling back.
+- Run the focused tests and confirm expected RED failures before production changes.
+- Update Runtime and EventAgent kind checks.
+- Re-run focused and full tests.
+
+### Observe
+
+Confirm that:
+
+- Runtime receives a real typed text event and still emits `chat_event_detected` plus tool execution.
+- EventAgent receives a real provider tool call and returns its arguments.
+- No direct ChatAgent tool transcript behavior appears in this fix.
+- The compatibility constructor is not used to hide production-path type mismatches in the updated tests.
+
+### Update
+
+- Mark 43 and 43.1 `done` only after spec and quality reviews pass.
+- Commit this repair separately with the regression and compatibility risk in the message.
+
+## Verification
+
+- `uv run pytest tests/test_debug_runtime.py tests/test_event_agent.py tests/test_openai_stream_parser.py -q`
+- `uv run pytest`
+- `git diff --check`

+ 65 - 0
docs/plans/todo-43.2-remove-legacy-event-consumption.md

@@ -0,0 +1,65 @@
+# Todo 43.2 Remove Legacy Event Consumption Plan
+
+**Status:** done
+
+## Result
+
+- Removed legacy `event` acceptance from Runtime and EventAgent production consumers.
+- Added wrong-source negative coverage.
+- Added a real chat-client `[DONE]` integration test for compatible providers without `finish_reason`.
+- Focused tests pass (`77 passed`) and the full suite passes (`82 passed`, one existing warning).
+
+## Goal
+
+Enforce typed event-source isolation at production consumer boundaries so the legacy compatibility constructor cannot silently mask incorrect ChatAgent or EventAgent wiring.
+
+## Scope
+
+- Runtime accepts only `text_event` from ChatAgent streams.
+- EventAgent accepts only `provider_tool_call` from its provider-tools argument request.
+- Remaining runtime/WebSocket test fixtures use the correct typed constructor.
+- Add negative tests for wrong-source events.
+- Add one chat-client SSE integration test proving `[DONE]` flush emits one provider tool call when no finish reason is present.
+- Keep the legacy constructor temporarily for unrelated external callers, but production consumers must not accept it.
+
+## Files
+
+- Modify: `src/agent_lab/application/runtime.py`
+- Modify: `src/agent_lab/application/event_agent.py`
+- Modify: `tests/test_debug_runtime.py`
+- Modify: `tests/test_event_agent.py`
+- Modify: `tests/test_websocket_api.py`
+
+## Plan
+
+### Plan
+
+1. Replace remaining production-path legacy fixtures with typed constructors.
+2. Add negative tests that wrong-source and legacy events do not cross the consumer boundaries.
+3. Add a MockTransport/SSE `[DONE]` integration test for the real chat client.
+4. Verify RED failures expose the three legacy consumer branches.
+5. Remove legacy consumption from Runtime/EventAgent and run all regressions.
+
+### Act
+
+- Runtime tests: emit `provider_tool_call` and legacy `event` from the ChatAgent fake and assert no tool handoff occurs; keep the positive `text_event` test.
+- EventAgent tests: emit `text_event`/legacy `event` from its provider fake and assert it falls back rather than treating either as resolved provider arguments; keep the positive provider call test.
+- WebSocket/client tests: replace legacy fixtures with typed constructors and add SSE chunks with provider tool calls, no `finish_reason`, then `[DONE]`; assert exactly one `provider_tool_call`.
+- Run focused tests and confirm expected failure before production changes.
+- Remove `event` from consumer condition sets.
+- Re-run focused and full tests.
+
+### Observe
+
+Confirm typed-source isolation is enforced by negative tests and that no remaining production-path fixture relies on `StreamItem.event(...)`.
+
+### Update
+
+- Mark 43, 43.1, and 43.2 `done` only after renewed spec and quality review.
+- Commit separately with the masked-regression risk in the message.
+
+## Verification
+
+- `uv run pytest tests/test_debug_runtime.py tests/test_event_agent.py tests/test_websocket_api.py tests/test_openai_stream_parser.py -q`
+- `uv run pytest`
+- `git diff --check`

+ 3 - 1
docs/plans/todos.md

@@ -69,7 +69,9 @@
 | 40 | done | `docs/plans/todo-40-chat-message-stream-audit.md` | Add audit events before ChatAgent visible message streaming starts and after it ends. | `uv run pytest` passes (`73 passed`, one existing Starlette deprecation warning); `node --check src/agent_lab/presentation/static/app.js`; `git diff --check` passes. |
 | 41 | done | `docs/plans/todo-41-session-button-feedback.md` | Add explicit Sessions-panel feedback for New, Refresh, and Load clicks. | `uv run pytest` passes (`73 passed`, one existing Starlette deprecation warning); `node --check src/agent_lab/presentation/static/app.js`; `git diff --check` passes. |
 | 42 | done | `docs/plans/todo-42-session-switch-idle-socket.md` | Allow switching sessions after a turn completes while the reusable WebSocket is still open. | `uv run pytest tests/test_websocket_api.py -q` passes (`37 passed`, one existing Starlette deprecation warning); `uv run pytest` passes (`74 passed`, one existing warning); `node --check src/agent_lab/presentation/static/app.js`; `git diff --check` passes. |
-| 43 | pending | `docs/plans/todo-43-typed-provider-tool-calls.md` | Preserve native provider tool calls as a distinct stream event without changing the existing text-event path. | Parser tests cover text events, fragmented/multiple provider calls, arguments, and `[DONE]` fallback. |
+| 43 | done | `docs/plans/todo-43-typed-provider-tool-calls.md` | Preserve native provider tool calls as a distinct stream event without changing the existing text-event path. | `uv run pytest tests/test_openai_stream_parser.py -q`; focused typed-event regressions; full suite passes (`82 passed`, one existing warning). |
+| 43.1 | done | `docs/plans/todo-43.1-typed-event-consumer-regression.md` | Repair Runtime and EventAgent consumers after typed stream kinds exposed legacy `event` assumptions. | Runtime consumes `text_event`, EventAgent consumes `provider_tool_call`; focused and full tests pass. |
+| 43.2 | done | `docs/plans/todo-43.2-remove-legacy-event-consumption.md` | Remove legacy `event` consumption from production paths and migrate remaining fixtures to typed stream kinds. | Wrong-source negative tests and real client `[DONE]` integration pass; full suite passes (`82 passed`). |
 | 44 | pending | `docs/plans/todo-44-provider-tool-transcript.md` | Add provider-compatible assistant tool-call and tool-result message serialization plus explicit tool-choice behavior. | Client/domain tests prove legal transcripts serialize and malformed tool history is rejected. |
 | 45 | pending | `docs/plans/todo-45-configurable-tool-invocation-mode.md` | Add `dual_agent` and `chat_agent_tools` runtime modes that share one registry and user-visible behavior. | Runtime tests prove mode-specific requests, direct execution, valid provider history, and dual-mode regression safety. |
 | 46 | pending | `docs/plans/todo-46-flat-event-policies-hybrid-resolution.md` | Extend flat event definitions with deterministic-first argument resolution, LLM fallback, and generic result policies. | Tests prove deterministic events skip EventAgent LLM and ambiguous cases use one bounded fallback. |