refactor: extract active turn lifecycle handling into dedicated modules#148
Merged
Conversation
…itor. Accumulate child streaming output for parent polling, add auto-cursor and cancel-aware waits, inherit parent ACP connections for child turns, and improve sub-agent list/transcript UX in the TUI.
Turns now execute inline on each session's actor task instead of a separately spawned task, so interrupting/closing a session could no longer be stopped via JoinHandle::abort() and would hang forever waiting on a provider response. Race the model query against the turn's cancellation token instead, and stop removing that token from the shared map when cancelling it (only finalize should remove it), since the removal raced with the query fetching its own clone and could silently hand it a fresh, disconnected token. Also fixes several self-deadlocks introduced by the actor refactor, where turn-completion code tried to read the currently-executing actor's own state through its mailbox (which is not polled again until the in-flight turn finishes): subagent stop hooks, goal accounting's plan-mode check, and duplicate "closed" notifications when a child agent's turn is interrupted mid-close. Additionally adds request/stream idle timeouts to the provider HTTP client so a stalled upstream connection can no longer wedge a turn indefinitely, and folds turn_exec.rs into a turn_exec/ module split for maintainability.
Reject malformed JSON-RPC payloads with ParseError/InvalidRequest responses before handler dispatch, and document stdio NDJSON framing.
…r concurrency. Replace the unbounded notification queue and multi-stage stdio writer with a single bounded OutboundFrame channel and OutboundWriter task, add semaphore-limited inbound dispatch with a fast path for client responses, and document that ACP session/prompt remains blocking while event-driven clients use _devo/turn/start.
Running tools now reuse the same Input rendering as completed tools, and cold code_search runs emit a progress notice before building the index.
…g bootstrap When another subscriber has already been installed (e.g. by tokio-console), LoggingBootstrap::install() now emits a warning and continues instead of returning an error. This allows optional diagnostic subscribers to coexist with the file-logging path without requiring callers to manage installation order.
Adds a tokio-console feature (gated behind cfg(feature = tokio-console)) that initializes a console-subscriber before the tokio runtime starts, enabling real-time async task inspection via tokio-console CLI. - arg0: new maybe_init_tokio_console() + wired into run_server_alias_dispatch - cli: forwarded feature + init before server logging in Command::Server - Both entry points (standalone devo-server and CLI-spawned server) covered - Environment variable TOKIO_CONSOLE must be set at runtime to activate - File logging is gracefully suppressed when console-subscriber takes over
Records every NDJSON frame sent and received to a structured trace file under DEVO_HOME/traces/ when DEVO_PROTOCOL_TRACE=1 is set. Useful for debugging client-server communication issues without modifying application-level logging. - Adds devo-util-paths dependency for DEVO_HOME resolution - Trace file location can be overridden with DEVO_PROTOCOL_TRACE_FILE - Each record includes monotonic seq, UTC timestamp, direction and payload
…bagent usage ownership - event_stream: drop overflow events instead of spawning unbounded tokio tasks that would block forever and prevent channel close - subagent_usage: track usage ownership per subagent turn for accurate parent-child token accounting across the agent tree - finalize: add stream idle timeout to provider HTTP client so a stalled upstream connection can no longer wedge a turn - items/turn_inline: consolidate inline item persistence to reduce mailbox round-trips during active turn execution
… and agent-delta fast path The turn event stream is a single point of failure: when broadcast_event blocks on outbound capacity, the event channel fills, enqueue_query_event spawns unbounded overflow tasks whose sender clones prevent channel close, and the session actor hangs forever on event_task.await. - outbound: add enqueue_outbound_notification with 200ms max wait before dropping, so streaming notifications never stall the event task - connection: add broadcast_streaming_agent_message_delta fast path that skips the full broadcast_event (no registry scans, no buffer locks) - subagent: change OutputBuffer::push to try_push_text_delta so wait_agent's lock does not gate token streaming to the TUI - items/handle: add non-blocking try_touch_last_activity + fallback item-seq counter to avoid mailbox round-trips from event-stream code - agent_message delta handlers use the new fast path; record_subagent_ output_event is moved after outbound delivery
…diff during research Research runs outside the session actor (unlike execute_turn_in_actor). Without an inline stream, every item persist/usage update sends blocking mailbox commands and can stall inbound handlers that need the same actor. - Add BeginInlineTurn / EndInlineTurn commands to install inline state for out-of-actor turns, with merge-back into actor state on completion - Register active_stream in begin_research_turn_stream so persist_item uses the fast inline path instead of the mailbox - Add record_parent_turn_totals_and_latest for research ledger snapshots TUI: /research turns now set active_turn_is_research so automatic git-diff overlays are suppressed during research sessions.
session-actor execution
This was referenced Jul 5, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.