|
terminal: session-broadcast sink + lifecycle events (Etap 1)
Persistent terminals emitted their stream only into a per-tool-call sink, which closed once the open action returned — so a background dev server's output stopped reaching the client immediately after open. TerminalClosed was never emitted at all (the handler existed, the emitter did not). Replace the per-tool event_sink with a single callback the orchestrator wires to the session's WebSocket(s): - TerminalManager: set_event_callback(cb) + _emit(session_id, event). Reader tasks and open/close deliver TerminalOutputDelta / TerminalOpened / TerminalClosed through the callback, which lives for the terminal's (and session's) lifetime — not the tool call's. - New TerminalOpened event (terminal_opened: name/description/pid/background). TerminalClosed now actually emitted from _close_one (explicit/idle/shutdown/ session_ended). Background output keeps streaming after open returns. - terminal.py: drop the per-tool event_sink from _tm.open (no longer needed). - orchestrator._on_terminal_event → _notify_session (per-session WS fan-out, same path recall/mcp updates use). container wires the callback after building the orchestrator. - Events imported lazily inside terminal_manager methods to avoid a circular import (navi.core.events → navi.core.__init__ → agent → registry → navi.tools). Tests: open emits TerminalOpened; background output streams via the callback after open returns (gap-3 fix); close emits TerminalClosed; no callback does not break readers. Existing terminal tests unchanged. Full suite: 968 passed, 1 skipped. Plan: docs/terminal_tool_plan.md (5 etaps, this is Etap 1). |
|---|
|
|
| docs/terminal_tool_plan.md 0 → 100644 |
|---|
| navi/core/container.py |
|---|
| navi/core/events.py |
|---|
| navi/core/orchestrator.py |
|---|
| navi/tools/_internal/terminal_manager.py |
|---|
| navi/tools/terminal.py |
|---|
| tests/unit/tools/test_terminal.py |
|---|