feat(agent_panel): unified agent panel 2c — composer routing + live daemon source#210
Merged
Conversation
…ppend_entry, refresh)
Contributor
There was a problem hiding this comment.
Pull request overview
Implements unified agent panel sub-phase 2c by routing the composer based on the selected conversation backend and wiring live Coven-daemon sessions into the merged conversation list + transcript pipeline, so daemon turns stream back into the shared agent_transcript model.
Changes:
- Add
ConversationBinding::LiveDaemonand routeOpenChatSession+ unified composer submits by backend (CLI → terminal PTY, daemon →cast_agentstream). - Extend
ChatModelwith a directappend_entrypath and daemon-session upsert (refresh_daemon_conversations) to support non-CLI event sources. - Implement daemon turn plumbing (
daemon_turn) plus an async spawn/buffer/100ms UI-poll drain loop inAgentPanelView.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| app/src/workspace/view.rs | Routes OpenChatSession and adds SubmitAgentPrompt handling for CLI PTY vs daemon streaming. |
| app/src/workspace/action.rs | Adds WorkspaceAction::SubmitAgentPrompt and marks it non-background. |
| app/src/cli_chat/view/transcript.rs | Allows transcript rendering for LiveDaemon bindings. |
| app/src/cli_chat/view/model_picker.rs | Allows model label resolution for LiveDaemon bindings. |
| app/src/cli_chat/model.rs | Adds daemon binding + direct entry append + live-daemon conversation refresh helpers. |
| app/src/cli_chat/model_tests.rs | Adds unit tests for daemon binding, append sequencing/no-op, and refresh idempotency. |
| app/src/cli_chat/conversation.rs | Introduces ConversationBinding::LiveDaemon. |
| app/src/agent_panel/view/transcript.rs | Allows transcript rendering for LiveDaemon bindings. |
| app/src/agent_panel/view/header.rs | Allows header label resolution for LiveDaemon bindings. |
| app/src/agent_panel/view/composer.rs | Enables composer for LiveDaemon only when cast_agent is available. |
| app/src/agent_panel/view_tests.rs | Adds unit test for the composer-active predicate. |
| app/src/agent_panel/mod.rs | Seeds live daemon sessions; adds buffered daemon stream plumbing + polling drain into the model; composer dispatches SubmitAgentPrompt. |
| app/src/agent_panel/daemon_turn.rs | New helper for building daemon messages and mapping daemon events into transcript entries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
7
to
11
| //! 2b builds the view shell (merged list + transcript + composer shell). It | ||
| //! reuses the `cli_chat` model layer and the shared `agent_transcript` | ||
| //! renderer; per-backend composer routing + the live daemon source arrive in | ||
| //! 2c. The composer submits via the shared `WorkspaceAction::SubmitChatPrompt` | ||
| //! (live CLI only in 2b). |
Comment on lines
+20903
to
+20926
| let session_id = session_id.clone(); | ||
| let text = text.clone(); | ||
| // Show the user's prompt immediately, then stream the reply. | ||
| let sid = session_id.clone(); | ||
| let prompt = text.clone(); | ||
| crate::cli_chat::model::ChatModel::handle(ctx).update(ctx, |model, ctx| { | ||
| model.append_entry( | ||
| &sid, | ||
| crate::agent_transcript::entry::ChatEntry { | ||
| sequence: 0, | ||
| created_at: chrono::Utc::now(), | ||
| kind: crate::agent_transcript::entry::ChatEntryKind::UserPrompt { | ||
| text: prompt, | ||
| }, | ||
| }, | ||
| ctx, | ||
| ); | ||
| }); | ||
| if let Some(view) = &self.agent_panel_view { | ||
| view.update(ctx, |panel, ctx| { | ||
| panel.start_daemon_turn(session_id, text, ctx); | ||
| }); | ||
| } | ||
| } |
Comment on lines
+191
to
+197
| Err(err) => { | ||
| log::info!("agent_panel: stream_agent_events failed: {err}"); | ||
| } | ||
| } | ||
| let mut state = task_buffer.lock().unwrap_or_else(|p| p.into_inner()); | ||
| state.in_flight = false; | ||
| }); |
Comment on lines
+140
to
+144
| /// Launch a daemon turn for `conversation_id` and stream its events into the | ||
| /// transcript. Mirrors `ai_assistant::panel`'s spawn-on-runtime + shared | ||
| /// buffer + 100ms UI-poll pattern. Unix-only (the daemon transport is a unix | ||
| /// socket); a no-op elsewhere. | ||
| #[cfg(all(feature = "cast-agent", unix))] |
This was referenced Jul 18, 2026
3 tasks
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.
Description
What: Implements sub-phase 2c of the unified agent panel (plan in #207) — the composer now routes by conversation backend, and live Coven-daemon sessions populate the merged list. Builds on 2a (#205) + 2b (#209, merged).
Why: 2b gave the unified panel a working shell with the CLI composer. 2c makes the daemon side live: selecting a daemon conversation lets you send to it, and the reply streams back into the same
agent_transcripttranscript.How:
ConversationBinding::LiveDaemon— a daemon conversation selected for input (no terminal; sends go through cast_agent).OpenChatSessionroutes by backend: daemon →bind_daemon, CLI →bind_past.ChatModel::append_entry— a direct entry-append path (daemon events aren'tCLIAgentEvents, so they can't go throughapply_event), assigning sequence, persisting, and emitting.ChatModel::refresh_daemon_conversations— upsert aDaemonconversation per liveCovenSession; seeded at panel construction from::ai::cast_agent::sessions()(alongside 2a's migrated history).WorkspaceAction::SubmitAgentPrompt(the unified composer now dispatches this): a live CLI binding → terminal PTY; aLiveDaemonbinding → append the user prompt, thenAgentPanelView::start_daemon_turnlaunchesstream_agent_eventsand a 100ms UI poll drains events →daemon_event_to_entry→append_entry. Mirrors the shippedai_assistantpanel's spawn/buffer/poll pattern. Composer is enabled forLiveDaemononly when the runtime is reachable (composer_is_active_for).Prompt delivery (resolved):
stream_agent_eventscarries the prompt in thePOST /api/v1/sessionslaunch body (launchMode:"stream") — no stdin user-frame. Each submit is one launch (session-per-turn); multi-turn daemon context continuity is out of scope.Gating: the daemon streaming is
cfg(all(feature = "cast-agent", unix))(the daemon transport is a unix socket).Linked Issue
Implements the 2c plan (#207). Continues the reconciliation roadmap (design #204; 2a #205; 2b #209; Phase 1 #201).
Testing
cargo nextest run -p warp-app --features cast-agent— 46 pass: new unit tests forLiveDaemonbinding,append_entrysequencing + unknown-conversation no-op,refresh_daemon_conversationsidempotency,daemon_turnmessage-build + event→entry mapping, and thecomposer_is_active_forpredicate — plus the full pre-existingcli_chat/agent_panel/agent_transcriptsuites unchanged.cargo check -p warp-app --bin cast-codes --features gui,cast-agentlinks.cargo clippy -p warp-app --features cast-agent --all-targets -- -D warningsclean;cargo fmt -- --checkclean../script/check_cli_chat_boundary,./script/check_ai_attribution,./script/check_rebrandpass.ai_assistantpath and is exercised bycrates/cast_agent's in-process daemon stub; a live coven-code turn wants manual verification with./script/run+ a running daemon.Agent Mode