Skip to content

[REMOTE-2149] Add runner config to orchestration (client)#13896

Open
warp-dev-github-integration[bot] wants to merge 11 commits into
masterfrom
factory/orchestration-runner-config
Open

[REMOTE-2149] Add runner config to orchestration (client)#13896
warp-dev-github-integration[bot] wants to merge 11 commits into
masterfrom
factory/orchestration-runner-config

Conversation

@warp-dev-github-integration

Copy link
Copy Markdown
Contributor

Description

Implements the warp client half of the optional runner config for orchestration (spec REMOTE-2149; server + proto in warp-server#12674). warp-proto-apis already ships runner_id on RunAgents.Remote and OrchestrationConfig.Remote.

An optional runner_id now threads through the remote execution-mode data model, proto conversions, RunAgentsExecutor, and per-child dispatch into each child's agent_config_snapshot, so a runner selected on run_agents / create_orchestration_config chooses the children's compute config. Omitting a runner is a no-op and preserves current behavior.

What's included:

  • Data model: runner_id added to the remote variants of RunAgentsExecutionMode, StartAgentExecutionMode, RunAgentsLaunchedExecutionMode, and OrchestrationExecutionMode, plus proto read/write and the auto-launch match check.
  • Feature flag: renamed CloudAgentRunnerCLICommandsCloudAgentRunners and reused it to gate a new Runner FilterableDropdown (populated by the existing getRunners query, with a "Use environment default" clear option) in the Stage 1 confirmation-card editor and the Stage 2 plan-card config block. CloudRunners (the run-cloud --runner flag) is untouched.
  • Dispatch: the resolved runner_id is propagated into each child's agent_config_snapshot in RunAgentsExecutor/launch_remote_child.
  • Runner selection preselects a requested runner, persists a manual pick, and survives streamed run_agents updates.

Runner options are fetched via getRunners (not cached client-side like environments) and the picker fills in when they load.

Linked Issue

Linear REMOTE-2149 (client portion). Tracked alongside the server/proto work in warp-server#12674; no separate GitHub issue.

Testing

  • I have manually tested my changes locally (dogfood build, cargo run --bin warp -- --api-key …, with computer use)
  • Rust unit tests: runner ↔ config proto round-trip, matches_active_config runner cases, build_runner_snapshot, set_runner_id round-trip, and the existing run_agents/start_agent/orchestration suites (unchanged) — all green.
  • cargo fmt, cargo clippy -D warnings, and cargo check (lib + tests) on the touched crates (ai, warp, warp_features, warp_cli) pass.
  • Computer-use walkthrough on the dogfood build: the confirmation card's Cloud mode shows the Runner dropdown populated from getRunners; selecting macOS 26 now persists (highlighted on reopen), matching the Environment picker.

Screenshots / Videos

The screenshots below trace the verification, ending with the Runner selector persisting a manually chosen runner.

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-NONE

Computer-use screenshots

The run_agents confirmation card in Cloud mode with the Runner dropdown expanded, showing options "Use environment default" (selected), "e2e-staging-runner", and "macOS 26".
Warp run_agents confirmation card in Cloud mode; Host = "macOS 26", Environment = "hubble-revops", but the Runner dropdown still displays "Use environment default" (before the fix).
The run_agents confirmation card in Cloud mode showing the Runner selector persisting the manually chosen value "macOS 26", alongside Environment set to "Feedback" (after the fix).

Conversation: https://staging.warp.dev/conversation/faad7878-9ba3-43c8-a59a-692b5e217a8a
Run: https://oz.staging.warp.dev/runs/019f7010-b584-70ed-91d3-b391f5322b73

This PR was generated with Oz.

Co-Authored-By: Warp agent@warp.dev

oz-agent added 4 commits July 17, 2026 13:54
Implements the warp-client half of the optional runner config for
orchestration (server/proto: warp-server#12674). Threads an optional
`runner_id` through the remote execution-mode data model, proto
conversions, `RunAgentsExecutor`, and the per-child dispatch into the
`agent_config_snapshot`, so a runner selected on `run_agents` /
`create_orchestration_config` chooses the children's compute config.

- Data model: add `runner_id` to the remote variants of
  `RunAgentsExecutionMode`, `StartAgentExecutionMode`,
  `RunAgentsLaunchedExecutionMode`, and `OrchestrationExecutionMode`,
  plus proto read/write and the auto-launch match check.
- Rename the `CloudAgentRunnerCLICommands` feature flag to
  `CloudAgentRunners` and use it to gate a new Runner dropdown in the
  Stage 1 confirmation-card editor and the Stage 2 plan-card config
  block (populated via the existing `getRunners` query).
- Show the launched runner, if any, in the card's terminal state.

Omitting a runner is a no-op and preserves current behavior.

Co-Authored-By: Oz <oz-agent@warp.dev>
- Re-apply the Runner dropdown selection after the streamed run_agents
  request finalizes (and on plan-card config refresh). The runner picker
  is excluded from the shared picker sync because its options load
  asynchronously and are cached on the view, so a late-arriving
  runner_id previously left the dropdown on "Use environment default".
- Revert the "Spawned N agents" terminal-state change so it no longer
  appends the runner UID (not helpful in the completion UI).

Co-Authored-By: Oz <oz-agent@warp.dev>
update_request runs on every stream chunk and overwrote the edit state
from the request, which usually omits a runner_id. That clobbered a
runner the user selected in the card (or one already resolved on the
call) back to "use environment default", and the runner picker never
re-reflected the requested runner. Preserve a non-empty runner when the
incoming request omits one; a request that carries a runner still wins.

Co-Authored-By: Oz <oz-agent@warp.dev>
A menu click dispatches SelectActionAndClose, which updates the edit
state via RunnerChanged but does not update the dropdown's displayed
selection; repopulating synchronously from the handler would panic with
"Circular view update". Defer the runner-picker re-sync to the next tick
so the closed dropdown reflects the runner the user picked. Verified with
computer use: selecting a runner now persists (matching the Environment
picker).

Co-Authored-By: Oz <oz-agent@warp.dev>
@cla-bot cla-bot Bot added the cla-signed label Jul 17, 2026
@oz-for-oss

oz-for-oss Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@warp-dev-github-integration[bot]

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 /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR threads runner_id through the orchestration data model, proto conversions, approved-config matching, launch dispatch, and adds runner selection controls to the run_agents confirmation and plan config cards. I did not find correctness, security, or spec-drift issues in the core runner propagation.

Concerns

  • The runner picker setup/fetch path is not fully feature/mode-gated, so hidden or local-mode cards can still call getRunners.

Verdict

Found: 0 critical, 0 important, 2 suggestions

Approve with nits

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

}
});
self.handles.pickers.runner_picker = Some(handle);
self.fetch_runners(ctx);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [SUGGESTION] Gate this runner-picker creation/fetch on CloudAgentRunners and remote mode; otherwise cards with the feature hidden (or Local selected) still call getRunners even though the Runner control is not rendered.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — extracted ensure_runner_picker, gated on CloudAgentRunners + remote mode and idempotent, called from ensure_pickers and on ExecutionModeToggled.

);
runner_handle.update(ctx, |d, c| d.set_use_overlay_layer(true, c));
self.pickers.runner_picker = Some(runner_handle);
self.fetch_runners(ctx);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [SUGGESTION] Apply the same CloudAgentRunners/remote-mode guard here so the plan config card does not fetch runners while the Runner control is hidden or irrelevant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — same CloudAgentRunners/remote-mode guard applied here.

.as_ref()
.map(|p| ChildView::new(p).finish()),
);
if warp_core::features::FeatureFlag::CloudAgentRunners.is_enabled() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import the FeatureFlag enum

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — added use warp_core::features::FeatureFlag; and switched the usages to FeatureFlag::CloudAgentRunners.

/// Fetches available runners via `getRunners` and repopulates the
/// Runner picker once they resolve. Runners are not cached
/// client-side (unlike environments), so this lazy fetch backs the
/// picker. No-op on wasm (no `FactoryClient` there).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make FactoryClient available on WASM - there's no reason it shouldn't be

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — FactoryClient is now available on WASM: removed the cfg(not(wasm)) gating on fetch_runners/imports, the wasm no-op stubs, and the expect(dead_code) attrs on get_factory_client.

.into_iter()
.map(|r| (r.uid.inner().to_string(), r.config.name))
.collect();
list.sort_by(|a, b| a.1.cmp(&b.1));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need a closure if using the default ordering

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — both surfaces now call get_runners(Some(RunnerSortBy::Name)) and the manual sort_by closure was dropped.

@@ -398,7 +449,6 @@
assert!(matches!(kind, StatusKind::Cancelled));
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add this whitespace back

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — restored the blank line.

}

/// Fetches available runners via `getRunners` and repopulates the
/// Runner picker once they resolve. No-op on wasm (no `FactoryClient`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticing that there's a lot of duplicate code between the orchestration config block and the run agents card. Would it be worth making a RunnerPicker view that handles the async fetch/syncing logic? It might not be with only two uses

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call-out. I kept the shared free functions in orchestration_controls.rs (create_runner_picker/populate_runner_picker/ensure_runner_picker) rather than introducing a dedicated RunnerPicker view, since there are only two call sites and both drive the same FilterableDropdown + RunnerChanged action through those helpers, so the duplication is already centralized. Happy to extract a proper view type in a follow-up if we add more surfaces.

Comment thread app/src/ai/orchestration/providers.rs Outdated

pub const ORCHESTRATION_WARP_WORKER_HOST: &str = WARP_WORKER_HOST;
pub const ORCHESTRATION_ENV_NONE_LABEL: &str = "Empty environment";
pub const ORCHESTRATION_RUNNER_NONE_LABEL: &str = "Use environment default";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this Use default

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — renamed the label to "Use default".

oz-agent added 3 commits July 17, 2026 18:11
Only build the Runner picker and call getRunners when the feature flag
is on and the card is in remote mode, and create it lazily on the
Local->Cloud toggle, so hidden or Local-mode cards never hit getRunners.

Co-Authored-By: Oz <oz-agent@warp.dev>
…on-runner-config

# Conflicts:
#	app/src/ai/agent/api/convert_from.rs
#	app/src/ai/agent/api/convert_from_tests.rs
#	app/src/ai/blocklist/action_model/execute/run_agents.rs
#	app/src/ai/blocklist/action_model/execute/start_agent.rs
#	app/src/ai/blocklist/action_model/execute/start_agent_tests.rs
#	app/src/ai/blocklist/block/view_impl/orchestration_tests.rs
#	app/src/ai/blocklist/block_tests.rs
#	app/src/ai/orchestration/config_state.rs
#	app/src/pane_group/pane/terminal_pane.rs
#	crates/ai/src/agent/action/mod.rs
- Gate runner picker creation/fetch on CloudAgentRunners + remote mode in both surfaces
- Import FeatureFlag enum in orchestration_controls
- Make FactoryClient available on WASM (drop cfg(not(wasm)) gating and dead-code attrs)
- Use default RunnerSortBy::Name ordering instead of manual sort closure
- Rename runner "none" label to "Use default"
- Restore whitespace and add runner_id to merged-in remote test cases

Co-Authored-By: Oz <oz-agent@warp.dev>
oz-agent added 4 commits July 17, 2026 19:25
The warp_tui orchestration block tests construct RunAgentsExecutionMode::Remote
and OrchestrationExecutionMode::Remote directly and needed the new runner_id
field, which broke Formatting + Clippy and the test builds across all platforms.

Co-Authored-By: Oz <oz-agent@warp.dev>
upsert_runner/delete_runner and UpsertedRunner back CLI commands that aren't
built for wasm, so they're dead code on wasm while get_runners still powers the
runner picker. Gate the dead_code lint to the wasm target only.

Co-Authored-By: Oz <oz-agent@warp.dev>
Merging master brought in crates/warp_tui/src/orchestration_model_tests.rs,
whose StartAgentExecutionMode::Remote construction needed the new runner_id
field. This broke clippy + tests on all native platforms.

Co-Authored-By: Oz <oz-agent@warp.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants