[QUALITY-569] Stage 2 Client: OrchestrationConfig on Plan Card + Auto-Launch + Disabled Card#9927
[QUALITY-569] Stage 2 Client: OrchestrationConfig on Plan Card + Auto-Launch + Disabled Card#9927cephalonaut wants to merge 21 commits intomasterfrom
Conversation
|
I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR adds client-side orchestration configuration on plan cards, dirty-sync transport for config updates, and auto-launch/deny behavior for matching run_agents actions.
Concerns
- The pending orchestration update is stored as a global document-model singleton and is piggybacked onto the next outbound request without checking the request's conversation, so edits in one conversation can be sent with another conversation's request.
Verdict
Found: 0 critical, 1 important, 1 suggestion
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
|
|
||
| if let Err(e) = self.send_request_input( | ||
| // Piggyback any pending orchestration config update. | ||
| if let Some(dirty_event) = AIDocumentModel::as_ref(ctx) |
There was a problem hiding this comment.
dirty_orchestration_event is a singleton, so the next request in any conversation can carry another conversation's config update; store the source conversation_id in the dirty event and only piggyback it when it matches this request's conversation.
There was a problem hiding this comment.
Keyed by conversation ID for now
| }; | ||
| let model_handle = oc::new_standard_picker_dropdown(&colors, ctx); | ||
| model_handle.update(ctx, |d, c| d.set_use_overlay_layer(true, c)); | ||
| oc::populate_model_picker(&model_handle, &display_model_id, ctx); |
There was a problem hiding this comment.
💡 [SUGGESTION] The plan-card model picker is populated once and never refreshed when LLMPreferences finishes loading; mirror the LLMPreferencesEvent::UpdatedAvailableLLMs subscription added to RunAgentsCardView so the dropdown isn't stuck empty or stale.
6c7be3a to
4ed836b
Compare
0a50692 to
708a42e
Compare
4ed836b to
ff84142
Compare
708a42e to
502c6e7
Compare
6266d02 to
79cbf6b
Compare
…ypes - Add OrchestrationConfig, OrchestrationExecutionMode, OrchestrationConfigStatus types in crates/ai/src/agent/orchestration_config.rs with matches_active_config() pure function and proto round-trip conversions (15 unit tests). - Extract shared orchestration controls into app/src/ai/blocklist/inline_action/orchestration_controls.rs: OrchestrationEditState, OrchestrationControlAction trait, generic picker creation/population/sync/render helpers (~720 lines). - Refactor RunAgentsCardView to delegate to shared module (1394→850 lines). All 19 existing card view tests pass unchanged. Co-Authored-By: Oz <oz-agent@warp.dev>
- Add conversation-level orchestration config fields: orchestration_config, orchestration_status, orchestration_plan_id, dirty_orchestration_event - Add DirtyOrchestrationEvent struct for dirty-sync transport - Add OrchestrationConfigUpdated event variant - Add accessors: active_orchestration_config(), orchestration_status(), dirty_orchestration_event(), clear_dirty_orchestration_event() - Add mutators: set_orchestration_config(), set_orchestration_status() - Add hydrate_orchestration_config_from_snapshot() for server snapshot ingestion - Handle new event variant in AIDocumentView and PlanAndTodoListView matches Co-Authored-By: Oz <oz-agent@warp.dev>
- Create OrchestrationConfigBlockView in app/src/ai/document/orchestration_config_block.rs with 'Use orchestration' toggle, Cloud/Local mode selector, and all picker dropdowns (harness, host, environment, base model) using shared controls. - Approved state shows full controls; disapproved state hides them. - Embed config block in AIDocumentView render above the editor content, conditionally shown when AIDocumentModel has an active orchestration config. - Subscribe to OrchestrationConfigUpdated events for re-rendering. - Field edits and toggle changes route through AIDocumentModel.set_orchestration_config() which sets the dirty flag for the dirty-sync transport (Phase 4). Co-Authored-By: Oz <oz-agent@warp.dev>
- Add AIAgentInput::OrchestrationConfigUpdate variant for piggybacking user config edits on outbound requests. - Hook BlocklistAIController.send_query() to collect the dirty event from AIDocumentModel before send_request_input, and clear it after. - Extend convert_input_to_user_input() to convert OrchestrationConfigUpdate to the proto OrchestrationConfigUpdate UserInput wire format. - Handle new variant in all exhaustive match statements across the codebase (redaction, persistence, telemetry, SDK driver, view_impl, etc.). Co-Authored-By: Oz <oz-agent@warp.dev>
Add auto-launch path: when the active orchestration config is approved and matches the request, the card immediately dispatches execute_run_agents() and renders in spawning state from the start (no confirmation UI). Add denied card: at construction, detect existing Denied results in history and render a static disabled card with Cancelled styling. Thread active orchestration config from AIDocumentModel through AIBlock::ensure_run_agents_card_view() to RunAgentsCardView::new(). Co-Authored-By: Oz <oz-agent@warp.dev>
The Flex::column() wrapping the editor gave unbounded height to its children. The editor's Scrollable requires a finite height constraint. Fix by making the editor an Expanded child so it fills remaining space after the config block with a bounded constraint. Co-Authored-By: Oz <oz-agent@warp.dev>
- Remove unused imports OrchestrationConfig and ModelHandle in orchestration_config_block.rs - Fix unused closure parameter ctx -> _ in controller.rs - Replace .clone() with copy dereference for UiComponentStyles in orchestration_controls.rs Co-Authored-By: Oz <oz-agent@warp.dev>
AIDocumentModel was missing the subscription to BlocklistAIHistoryModel that triggers scanning for OrchestrationConfigSnapshot messages in the conversation task list. Without this, the server-set config never populated the model and the plan card config block never appeared. - Subscribe to AppendedExchange, UpdatedStreamingExchange, and RestoredConversations events - Scan all tasks in the conversation for the OrchestrationConfigSnapshot message variant - Clone the snapshot to release the history borrow before calling hydrate_orchestration_config_from_snapshot with &mut ctx Co-Authored-By: Oz <oz-agent@warp.dev>
Auto-launch was triggering unintentionally because AIDocumentModel is a singleton that carries orchestration config across conversations. A config set in one conversation would cause run_agents calls in unrelated conversations to auto-launch without showing the confirmation card. Disable auto-launch entirely (hardcode false) until the active config is properly scoped to the owning conversation. The confirmation card flow continues to work normally. Co-Authored-By: Oz <oz-agent@warp.dev>
…rsation AIConversation The orchestration config (OrchestrationConfig, OrchestrationConfigStatus, orchestration_plan_id) was stored as singleton fields on AIDocumentModel, a global singleton shared across all conversations. This caused stale config from one conversation to leak into unrelated conversations, triggering incorrect auto-launches of the RunAgents card. Fix: move these three fields to AIConversation so each conversation owns its own config. Update all readers (OrchestrationConfigBlockView, AIDocumentView, ensure_run_agents_card_view in block.rs) to read from the conversation via BlocklistAIHistoryModel instead of the singleton. The dirty_orchestration_event field stays on AIDocumentModel since it is about outbound sync, not conversation state. Re-enable auto-launch in RunAgentsCardView (previously hardcoded to false as a workaround) with an additional guard against empty configs. Co-Authored-By: Oz <oz-agent@warp.dev>
- Add 1px horizontal divider between description and controls section - Initialize pickers in constructor when config is already approved - Use accent_overlay_2 for active Cloud/Local segment on plan card - Replace text On/Off toggle with pill-shaped switch widget (36x18) Co-Authored-By: Oz <oz-agent@warp.dev>
The model picker dropdown on the RunAgentsCardView confirmation card was not populating because LLMPreferences loads model choices asynchronously from the server. The picker was populated once in ensure_pickers() but never refreshed when new models arrived. Subscribe to LLMPreferencesEvent::UpdatedAvailableLLMs to repopulate the model picker when available models change, matching the pattern used by ModelSelector, AISettingsPage, and other model picker consumers in the codebase. Also removes the unused active_config parameter from RunAgentsCardView::new() (auto-launch is currently disabled) and cleans up the associated dead code at the call site. Co-Authored-By: Oz <oz-agent@warp.dev>
…irty-sync - Move orchestration config from AIDocumentModel singleton to per-conversation AIConversation storage (follows todo_lists pattern) - Plan card UI: pill toggle, View details link, vertical pickers, full-width layout - Confirmation card: LLMPreferences subscription for async model loading - Model picker: use set_selected_by_name instead of set_selected_by_index - Picker dropdowns: remove 190px max width cap, overlay layer for plan card - Dirty-sync: preserve plan_id on user edits, default empty worker_host to warp - Auto-launch: deferred to stream completion via ActionBlockedOnUserConfirmation - matches_active_config: clean up after debug log removal Co-Authored-By: Oz <oz-agent@warp.dev>
- Replace scan-all-messages with reactive OrchestrationConfigSnapshot handling in apply_client_action(), keeping scan only for restore path (now finds last snapshot, not first) - New BlocklistAIHistoryEvent::OrchestrationConfigUpdated for reactive path - Only clear dirty_orchestration_event on successful send (N2) - Add OrchestrationConfigUpdate telemetry variant instead of reusing PassiveSuggestionResult (N1) - Move pill toggle construction inside Hoverable closure (N6) - Simplify matches_active_config match to tail expression (T2) - Remove redundant function-scoped import (T3) - Fix _app parameter name in AIDocumentView::render (T1) Co-Authored-By: Oz <oz-agent@warp.dev>
Extract should_auto_launch() and compute_is_denied() as testable pure functions. Tests cover: happy paths, guard conditions (already launched, denied, spawning, editor open, empty configs), config matching (model, harness, execution mode, field inheritance), and denied-flag computation (history result, disapproved config, combined states). Co-Authored-By: Oz <oz-agent@warp.dev>
- Config block view and document view subscribe directly to BlocklistAIHistoryEvent::OrchestrationConfigUpdated, removing the AIDocumentModel passthrough relay - Remove AIDocumentModelEvent::OrchestrationConfigUpdated variant (no subscribers remain) - Replace FQN paths with top-level imports in agent/mod.rs - Remove process-internal 'Stage 1'/'Stage 2' references from comments Co-Authored-By: Oz <oz-agent@warp.dev>
…g Figma mock Co-Authored-By: Oz <oz-agent@warp.dev>
- Replace orchestration_event_streamer.rs with master's version, add OrchestrationConfigUpdated to ignore list - Add active_config parameter back to RunAgentsCardView::new() and pass it from block.rs - Fix output.rs: use singular open_skill_button_handle/read_from_skill_button_handle (not HashMap) - Add missing orchestration_config imports to run_agents_card_view.rs Co-Authored-By: Oz <oz-agent@warp.dev>
- Refactor dirty_orchestration_event from a single Option to a HashMap<AIConversationId, DirtyOrchestrationEvent> so switching conversations doesn't clobber pending config updates. - Controller takes and clears only the matching conversation's entry; re-inserts on send failure to avoid silent loss. - Remove conversation_id from DirtyOrchestrationEvent (the HashMap key provides the scoping). - Subscribe OrchestrationConfigBlockView to LLMPreferencesEvent::UpdatedAvailableLLMs so the model picker refreshes when LLM preferences load asynchronously. Co-Authored-By: Oz <oz-agent@warp.dev>
79cbf6b to
b563051
Compare
|
Advait - this is dependent on https://github.com/warpdotdev/warp-server/pull/10854 which Suraj is still reviewing |
Description
Adds the client-side orchestration config UI on plan cards, auto-launch for matching
run_agentstool calls, and per-conversation config scoping. This builds on top of the Stage 1 confirmation card and shared controls.Demo: https://www.loom.com/share/18e96159e91641e3b6a78924ea1b9f76
What
Plan card config block — An inline config block on plan cards with:
OrchestrationConfigUpdateAuto-launch — When the user approves a config and the agent sends a matching
run_agentstool call, the confirmation card is skipped and agents spawn immediately. Deferred to stream completion viaActionBlockedOnUserConfirmationto handle streaming timing.Per-conversation scoping — Orchestration config moved from the
AIDocumentModelsingleton to per-conversationAIConversationstorage (following thetodo_listspattern), preventing config from one conversation leaking into another.Reactive config hydration —
OrchestrationConfigSnapshotmessages are processed inline inapply_client_action()as they arrive, rather than scanning all messages on every streaming update. Scanning is only used for conversation restore.Architecture
crates/ai/src/agent/orchestration_config.rs— Rust-native types,matches_active_config()with 15 unit testsapp/src/ai/blocklist/inline_action/orchestration_controls.rs— Shared controls (trait-based generic pickers) used by both the confirmation card editor and the plan card config blockapp/src/ai/document/orchestration_config_block.rs— Plan card config block viewBlocklistAIHistoryEvent::OrchestrationConfigUpdated(no passthrough relay)Testing
run_agents_card_view(21 new covering auto-launch/auto-deny decision logic)orchestration_config(matching, proto round-trips)Server API dependencies
OrchestrationConfigSnapshotandOrchestrationConfigUpdateproto messages (already deployed)Agent Mode
Conversation | Plan
Co-Authored-By: Oz oz-agent@warp.dev