99 lines
3.4 KiB
Rust
99 lines
3.4 KiB
Rust
use warp_cli::agent::Harness;
|
|
|
|
use crate::features::FeatureFlag;
|
|
#[cfg(not(target_family = "wasm"))]
|
|
use crate::util::path::resolve_executable;
|
|
|
|
/// Tooltip shown when a local harness is product-enabled but its CLI is missing.
|
|
pub(crate) const LOCAL_HARNESS_INSTALLATION_REQUIRED_TOOLTIP: &str =
|
|
"Install Claude Code to use this local harness.";
|
|
pub(crate) const LOCAL_CODEX_HARNESS_INSTALLATION_REQUIRED_TOOLTIP: &str =
|
|
"Install Codex to use this local harness.";
|
|
pub(crate) const LOCAL_CODEX_HARNESS_DISABLED_MESSAGE: &str =
|
|
"Local Codex child agents are temporarily disabled.";
|
|
|
|
/// Client-side readiness for using a harness in local orchestration.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub(crate) enum LocalHarnessSetupState {
|
|
/// The harness is product-enabled and its required local CLI is installed.
|
|
Ready,
|
|
/// The harness is intentionally unavailable in the product.
|
|
ProductDisabled { message: &'static str },
|
|
/// The harness is product-enabled but the required local CLI is missing.
|
|
MissingHarness { tooltip: &'static str },
|
|
}
|
|
|
|
impl LocalHarnessSetupState {
|
|
/// Returns whether the harness can be selected in local orchestration controls.
|
|
pub(crate) fn is_selectable(self) -> bool {
|
|
matches!(self, Self::Ready)
|
|
}
|
|
}
|
|
|
|
/// Returns the product-level disabled reason for a local harness.
|
|
pub(crate) fn local_harness_product_disabled_message(harness: Harness) -> Option<&'static str> {
|
|
match harness {
|
|
Harness::Codex if !local_codex_harness_is_enabled() => {
|
|
Some(LOCAL_CODEX_HARNESS_DISABLED_MESSAGE)
|
|
}
|
|
Harness::Oz | Harness::Claude | Harness::OpenCode | Harness::Gemini | Harness::Unknown => {
|
|
None
|
|
}
|
|
Harness::Codex => None,
|
|
}
|
|
}
|
|
|
|
fn local_codex_harness_is_enabled() -> bool {
|
|
FeatureFlag::LocalClaudeCodexChildHarnesses.is_enabled()
|
|
}
|
|
|
|
/// Returns whether a local harness is exposed by product policy.
|
|
pub(crate) fn local_harness_is_product_enabled(harness: Harness) -> bool {
|
|
local_harness_product_disabled_message(harness).is_none()
|
|
}
|
|
|
|
/// Returns the current local setup state for a harness.
|
|
pub(crate) fn local_harness_setup_state(harness: Harness) -> LocalHarnessSetupState {
|
|
local_harness_setup_state_with_cli_resolver(harness, local_cli_is_installed)
|
|
}
|
|
|
|
fn local_harness_setup_state_with_cli_resolver(
|
|
harness: Harness,
|
|
cli_is_installed: impl Fn(&str) -> bool,
|
|
) -> LocalHarnessSetupState {
|
|
if let Some(message) = local_harness_product_disabled_message(harness) {
|
|
return LocalHarnessSetupState::ProductDisabled { message };
|
|
}
|
|
|
|
match harness {
|
|
Harness::Claude if !cli_is_installed("claude") => LocalHarnessSetupState::MissingHarness {
|
|
tooltip: LOCAL_HARNESS_INSTALLATION_REQUIRED_TOOLTIP,
|
|
},
|
|
Harness::Codex if !cli_is_installed("codex") => LocalHarnessSetupState::MissingHarness {
|
|
tooltip: LOCAL_CODEX_HARNESS_INSTALLATION_REQUIRED_TOOLTIP,
|
|
},
|
|
Harness::Oz
|
|
| Harness::Claude
|
|
| Harness::OpenCode
|
|
| Harness::Gemini
|
|
| Harness::Codex
|
|
| Harness::Unknown => LocalHarnessSetupState::Ready,
|
|
}
|
|
}
|
|
|
|
fn local_cli_is_installed(command: &str) -> bool {
|
|
#[cfg(not(target_family = "wasm"))]
|
|
{
|
|
resolve_executable(command).is_some()
|
|
}
|
|
#[cfg(target_family = "wasm")]
|
|
{
|
|
let _ = command;
|
|
false
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "local_harness_setup_tests.rs"]
|
|
mod tests;
|