Complete agent monitoring and Galaxy Control integration
- expose command-monitor conversations and preserve visible agent transcripts - add bounded polling and a dedicated shell interrupt tool - improve direct-provider images, skills, tool history, and usage handling - package and brand Galaxy Control across releases, installers, persistence, and docs
This commit is contained in:
@@ -668,12 +668,16 @@ pub enum WorkspaceAction {
|
||||
/// Uninstall the Oz CLI command from /usr/local/bin
|
||||
#[cfg(target_os = "macos")]
|
||||
UninstallOz,
|
||||
/// Install the Warp Control CLI command to /usr/local/bin
|
||||
/// Allow local Galaxy Control clients to automate this app.
|
||||
EnableGalaxyControl,
|
||||
/// Reject local Galaxy Control clients and withdraw discovery credentials.
|
||||
DisableGalaxyControl,
|
||||
/// Install the Galaxy Control CLI command to /usr/local/bin
|
||||
#[cfg(target_os = "macos")]
|
||||
InstallWarpctrl,
|
||||
/// Uninstall the Warp Control CLI command from /usr/local/bin
|
||||
InstallGalaxyctrl,
|
||||
/// Uninstall the Galaxy Control CLI command from /usr/local/bin
|
||||
#[cfg(target_os = "macos")]
|
||||
UninstallWarpctrl,
|
||||
UninstallGalaxyctrl,
|
||||
UndoRevertInCodeReviewPane {
|
||||
window_id: WindowId,
|
||||
view_id: EntityId,
|
||||
@@ -1211,8 +1215,9 @@ impl WorkspaceAction {
|
||||
SampleProcess => false,
|
||||
#[cfg(target_os = "macos")]
|
||||
InstallOz | UninstallOz => false,
|
||||
EnableGalaxyControl | DisableGalaxyControl => false,
|
||||
#[cfg(target_os = "macos")]
|
||||
InstallWarpctrl | UninstallWarpctrl => false,
|
||||
InstallGalaxyctrl | UninstallGalaxyctrl => false,
|
||||
#[cfg(feature = "local_fs")]
|
||||
FileRenamed { .. } => false, // File rename doesn't change workspace state
|
||||
#[cfg(feature = "local_fs")]
|
||||
|
||||
@@ -12,20 +12,20 @@ fn oz_install_target_path() -> PathBuf {
|
||||
PathBuf::from("/usr/local/bin").join(ChannelState::channel().cli_command_name())
|
||||
}
|
||||
|
||||
/// Compute the target path where the Warp Control symlink should be installed, based on channel
|
||||
fn warpctrl_install_target_path() -> PathBuf {
|
||||
PathBuf::from("/usr/local/bin").join(ChannelState::channel().warpctrl_command_name())
|
||||
/// Compute the target path where the Galaxy Control symlink should be installed, based on channel
|
||||
fn galaxyctrl_install_target_path() -> PathBuf {
|
||||
PathBuf::from("/usr/local/bin").join(ChannelState::channel().galaxyctrl_command_name())
|
||||
}
|
||||
|
||||
/// Compute the source path of the warpctrl wrapper inside the current app bundle.
|
||||
/// Compute the source path of the galaxyctrl wrapper inside the current app bundle.
|
||||
///
|
||||
/// Oz commands are part of the shared executable's normal argument parser, so
|
||||
/// Oz can symlink directly to the current executable. Warp Control has a
|
||||
/// separate parser selected by the hidden `--warpctrl` flag, so its installed
|
||||
/// Oz can symlink directly to the current executable. Galaxy Control has a
|
||||
/// separate parser selected by the hidden `--galaxyctrl` flag, so its installed
|
||||
/// symlink must target the bundled wrapper that injects that flag. Without it,
|
||||
/// Warp Control subcommands such as `tab` would reach the normal parser and be
|
||||
/// Galaxy Control subcommands such as `tab` would reach the normal parser and be
|
||||
/// rejected as unknown.
|
||||
fn warpctrl_bundle_source_path() -> Result<PathBuf> {
|
||||
fn galaxyctrl_bundle_source_path() -> Result<PathBuf> {
|
||||
let current_binary =
|
||||
std::env::current_exe().context("Failed to get current executable path")?;
|
||||
let bundle_root = current_binary
|
||||
@@ -35,7 +35,7 @@ fn warpctrl_bundle_source_path() -> Result<PathBuf> {
|
||||
.ok_or_else(|| anyhow!("Current executable is not inside a bundled app"))?;
|
||||
Ok(bundle_root
|
||||
.join("Contents/Resources/bin")
|
||||
.join(ChannelState::channel().warpctrl_command_name()))
|
||||
.join(ChannelState::channel().galaxyctrl_command_name()))
|
||||
}
|
||||
fn path_resolves_to(path: &Path, expected_path: &Path) -> bool {
|
||||
let Ok(path) = path.canonicalize() else {
|
||||
@@ -47,12 +47,12 @@ fn path_resolves_to(path: &Path, expected_path: &Path) -> bool {
|
||||
path == expected_path
|
||||
}
|
||||
|
||||
/// Whether the installed Warp Control command resolves to this app bundle's wrapper.
|
||||
pub fn is_warpctrl_installed() -> bool {
|
||||
let Ok(source) = warpctrl_bundle_source_path() else {
|
||||
/// Whether the installed Galaxy Control command resolves to this app bundle's wrapper.
|
||||
pub fn is_galaxyctrl_installed() -> bool {
|
||||
let Ok(source) = galaxyctrl_bundle_source_path() else {
|
||||
return false;
|
||||
};
|
||||
path_resolves_to(&warpctrl_install_target_path(), &source)
|
||||
path_resolves_to(&galaxyctrl_install_target_path(), &source)
|
||||
}
|
||||
|
||||
/// Create a symlink with elevated privileges using osascript
|
||||
@@ -213,29 +213,29 @@ pub fn uninstall_oz() -> Result<()> {
|
||||
uninstall_symlink(&oz_install_target_path(), "Oz command")
|
||||
}
|
||||
|
||||
/// Install Warp Control by symlinking its bundled wrapper into /usr/local/bin.
|
||||
/// Install Galaxy Control by symlinking its bundled wrapper into /usr/local/bin.
|
||||
///
|
||||
/// The wrapper contains no control implementation. It resolves this installed
|
||||
/// symlink back into the app bundle, launches the shared Warp executable, and
|
||||
/// injects `--warpctrl` so startup selects the separate Warp Control parser
|
||||
/// symlink back into the app bundle, launches the shared Galaxy executable, and
|
||||
/// injects `--galaxyctrl` so startup selects the separate Galaxy Control parser
|
||||
/// before normal parsing or GUI startup.
|
||||
pub fn install_warpctrl() -> Result<()> {
|
||||
let warpctrl_path = warpctrl_install_target_path();
|
||||
let warpctrl_source = warpctrl_bundle_source_path()?;
|
||||
pub fn install_galaxyctrl() -> Result<()> {
|
||||
let galaxyctrl_path = galaxyctrl_install_target_path();
|
||||
let galaxyctrl_source = galaxyctrl_bundle_source_path()?;
|
||||
|
||||
if !warpctrl_source.exists() {
|
||||
if !galaxyctrl_source.exists() {
|
||||
return Err(anyhow!(
|
||||
"Cannot install Warp Control CLI: bundled wrapper not found at {}",
|
||||
warpctrl_source.display()
|
||||
"Cannot install Galaxy Control CLI: bundled wrapper not found at {}",
|
||||
galaxyctrl_source.display()
|
||||
));
|
||||
}
|
||||
|
||||
install_symlink(&warpctrl_source, &warpctrl_path, "Warp Control CLI")
|
||||
install_symlink(&galaxyctrl_source, &galaxyctrl_path, "Galaxy Control CLI")
|
||||
}
|
||||
|
||||
/// Uninstall the Warp Control CLI by removing the symlink from /usr/local/bin
|
||||
pub fn uninstall_warpctrl() -> Result<()> {
|
||||
uninstall_symlink(&warpctrl_install_target_path(), "Warp Control command")
|
||||
/// Uninstall the Galaxy Control CLI by removing the symlink from /usr/local/bin
|
||||
pub fn uninstall_galaxyctrl() -> Result<()> {
|
||||
uninstall_symlink(&galaxyctrl_install_target_path(), "Galaxy Control command")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1190,6 +1190,25 @@ pub fn init(app: &mut AppContext) {
|
||||
.with_group(bindings::BindingGroup::Settings.as_str())
|
||||
.with_context_predicate(id!("Workspace") & !id!("IsAnonymousUser"))]);
|
||||
|
||||
if FeatureFlag::GalaxyControlCli.is_enabled() {
|
||||
app.register_editable_bindings([
|
||||
EditableBinding::new(
|
||||
"workspace:enable_galaxy_control",
|
||||
"Enable Galaxy Control",
|
||||
WorkspaceAction::EnableGalaxyControl,
|
||||
)
|
||||
.with_group(bindings::BindingGroup::Settings.as_str())
|
||||
.with_context_predicate(id!("Workspace") & !id!(flags::GALAXY_CONTROL_ENABLED)),
|
||||
EditableBinding::new(
|
||||
"workspace:disable_galaxy_control",
|
||||
"Disable Galaxy Control",
|
||||
WorkspaceAction::DisableGalaxyControl,
|
||||
)
|
||||
.with_group(bindings::BindingGroup::Settings.as_str())
|
||||
.with_context_predicate(id!("Workspace") & id!(flags::GALAXY_CONTROL_ENABLED)),
|
||||
]);
|
||||
}
|
||||
|
||||
if !FeatureFlag::AvatarInTabBar.is_enabled() {
|
||||
app.register_editable_bindings([EditableBinding::new(
|
||||
"workspace:toggle_resource_center",
|
||||
@@ -1211,7 +1230,7 @@ pub fn init(app: &mut AppContext) {
|
||||
.with_context_predicate(id!("Workspace") & id!(flags::ENABLE_WARP_DRIVE))]);
|
||||
}
|
||||
|
||||
// Oz and Warp Control CLI install/uninstall actions (macOS only)
|
||||
// Oz and Galaxy Control CLI install/uninstall actions (macOS only)
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
app.register_editable_bindings([
|
||||
@@ -1230,19 +1249,19 @@ pub fn init(app: &mut AppContext) {
|
||||
.with_group(bindings::BindingGroup::Settings.as_str())
|
||||
.with_context_predicate(id!("Workspace")),
|
||||
]);
|
||||
if FeatureFlag::WarpControlCli.is_enabled() {
|
||||
if FeatureFlag::GalaxyControlCli.is_enabled() {
|
||||
app.register_editable_bindings([
|
||||
EditableBinding::new(
|
||||
"workspace:install_warpctrl",
|
||||
"Install Warp Control CLI globally for use outside of Warp",
|
||||
WorkspaceAction::InstallWarpctrl,
|
||||
"workspace:install_galaxyctrl",
|
||||
"Install Galaxy Control CLI globally",
|
||||
WorkspaceAction::InstallGalaxyctrl,
|
||||
)
|
||||
.with_group(bindings::BindingGroup::Settings.as_str())
|
||||
.with_context_predicate(id!("Workspace")),
|
||||
EditableBinding::new(
|
||||
"workspace:uninstall_warpctrl",
|
||||
"Undo global Warp Control CLI installation (warpctrl will still work within Warp)",
|
||||
WorkspaceAction::UninstallWarpctrl,
|
||||
"workspace:uninstall_galaxyctrl",
|
||||
"Remove global Galaxy Control CLI installation",
|
||||
WorkspaceAction::UninstallGalaxyctrl,
|
||||
)
|
||||
.with_group(bindings::BindingGroup::Settings.as_str())
|
||||
.with_context_predicate(id!("Workspace")),
|
||||
|
||||
+53
-24
@@ -337,8 +337,8 @@ use crate::settings::{
|
||||
AccessibilitySettings, AliasExpansionSettings, AppEditorSettings, BlockVisibilitySettings,
|
||||
ChangelogSettings, CodeSettings, CodeSettingsChangedEvent, CtrlTabBehavior, CursorBlink,
|
||||
DebugSettings, DefaultSessionMode, FontSettings, GPUSettings, InputModeSettings, InputSettings,
|
||||
MonospaceFontSize, PaneSettings, PrivacySettings, SelectionSettings, Settings, SshSettings,
|
||||
ThemeSettings,
|
||||
LocalControlMode, LocalControlSettings, MonospaceFontSize, PaneSettings, PrivacySettings,
|
||||
SelectionSettings, Settings, SshSettings, ThemeSettings,
|
||||
};
|
||||
use crate::settings_view::keybindings::{KeybindingChangedEvent, KeybindingChangedNotifier};
|
||||
use crate::settings_view::mcp_servers_page::MCPServersSettingsPage;
|
||||
@@ -3154,6 +3154,11 @@ impl Workspace {
|
||||
ctx.notify();
|
||||
}
|
||||
});
|
||||
if FeatureFlag::GalaxyControlCli.is_enabled() {
|
||||
ctx.subscribe_to_model(&LocalControlSettings::handle(ctx), |_, _, _, ctx| {
|
||||
ctx.notify();
|
||||
});
|
||||
}
|
||||
|
||||
let toast_stack =
|
||||
ctx.add_typed_action_view(|_| DismissibleToastStack::new(Duration::from_secs(4)));
|
||||
@@ -8866,39 +8871,40 @@ impl Workspace {
|
||||
);
|
||||
}
|
||||
|
||||
/// Install the Warp Control CLI by creating a symlink in /usr/local/bin
|
||||
/// Install the Galaxy Control CLI by creating a symlink in /usr/local/bin
|
||||
#[cfg(target_os = "macos")]
|
||||
fn install_warpctrl(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
fn install_galaxyctrl(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
ctx.spawn(
|
||||
async { cli_install::install_warpctrl() },
|
||||
async { cli_install::install_galaxyctrl() },
|
||||
|view, result, ctx| {
|
||||
let command_name = ChannelState::channel().warpctrl_command_name();
|
||||
let message = format!("Installed the Warp Control CLI globally. You can now run '{command_name}' from any terminal outside of Warp.");
|
||||
let command_name = ChannelState::channel().galaxyctrl_command_name();
|
||||
let message = format!(
|
||||
"Galaxy Control CLI installed globally. You can now run '{command_name}' from any terminal."
|
||||
);
|
||||
let toast = DismissibleToast::success(message);
|
||||
view.handle_cli_command_result(
|
||||
result,
|
||||
toast,
|
||||
"Failed to install Warp Control command",
|
||||
"Failed to install Galaxy Control command",
|
||||
ctx,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Uninstall the Warp Control CLI by removing the symlink from /usr/local/bin
|
||||
/// Uninstall the Galaxy Control CLI by removing the symlink from /usr/local/bin
|
||||
#[cfg(target_os = "macos")]
|
||||
fn uninstall_warpctrl(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
fn uninstall_galaxyctrl(&mut self, ctx: &mut ViewContext<Self>) {
|
||||
ctx.spawn(
|
||||
async { cli_install::uninstall_warpctrl() },
|
||||
async { cli_install::uninstall_galaxyctrl() },
|
||||
|view, result, ctx| {
|
||||
let toast = DismissibleToast::success(
|
||||
"Removed the global Warp Control CLI installation — it still works inside Warp."
|
||||
.to_string(),
|
||||
"Removed the global Galaxy Control CLI installation.".to_string(),
|
||||
);
|
||||
view.handle_cli_command_result(
|
||||
result,
|
||||
toast,
|
||||
"Failed to uninstall Warp Control command",
|
||||
"Failed to uninstall Galaxy Control command",
|
||||
ctx,
|
||||
);
|
||||
},
|
||||
@@ -12274,13 +12280,15 @@ impl Workspace {
|
||||
source: AddTabWithShellSource,
|
||||
ctx: &mut ViewContext<Self>,
|
||||
) {
|
||||
send_telemetry_from_ctx!(
|
||||
TelemetryEvent::AddTabWithShell {
|
||||
source,
|
||||
shell: shell.telemetry_value()
|
||||
},
|
||||
ctx
|
||||
);
|
||||
if !matches!(source, AddTabWithShellSource::LocalControl) {
|
||||
send_telemetry_from_ctx!(
|
||||
TelemetryEvent::AddTabWithShell {
|
||||
source,
|
||||
shell: shell.telemetry_value()
|
||||
},
|
||||
ctx
|
||||
);
|
||||
}
|
||||
self.add_new_session_tab_with_default_mode(
|
||||
NewSessionSource::Tab,
|
||||
Some(ctx.window_id()),
|
||||
@@ -14373,7 +14381,9 @@ impl Workspace {
|
||||
|
||||
ctx.focus(&self.palette);
|
||||
|
||||
send_telemetry_from_ctx!(TelemetryEvent::PaletteSearchOpened { mode, source }, ctx);
|
||||
if !matches!(source, PaletteSource::LocalControl) {
|
||||
send_telemetry_from_ctx!(TelemetryEvent::PaletteSearchOpened { mode, source }, ctx);
|
||||
}
|
||||
|
||||
ctx.notify();
|
||||
}
|
||||
@@ -23830,10 +23840,24 @@ impl TypedActionView for Workspace {
|
||||
InstallOz => self.install_oz(ctx),
|
||||
#[cfg(target_os = "macos")]
|
||||
UninstallOz => self.uninstall_oz(ctx),
|
||||
EnableGalaxyControl => {
|
||||
LocalControlSettings::handle(ctx).update(ctx, |settings, ctx| {
|
||||
report_if_error!(settings
|
||||
.local_control_mode
|
||||
.set_value(LocalControlMode::Enabled, ctx));
|
||||
});
|
||||
}
|
||||
DisableGalaxyControl => {
|
||||
LocalControlSettings::handle(ctx).update(ctx, |settings, ctx| {
|
||||
report_if_error!(settings
|
||||
.local_control_mode
|
||||
.set_value(LocalControlMode::Disabled, ctx));
|
||||
});
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
InstallWarpctrl => self.install_warpctrl(ctx),
|
||||
InstallGalaxyctrl => self.install_galaxyctrl(ctx),
|
||||
#[cfg(target_os = "macos")]
|
||||
UninstallWarpctrl => self.uninstall_warpctrl(ctx),
|
||||
UninstallGalaxyctrl => self.uninstall_galaxyctrl(ctx),
|
||||
UndoRevertInCodeReviewPane { window_id, view_id } => {
|
||||
self.undo_revert_in_code_review_pane(*window_id, *view_id, ctx)
|
||||
}
|
||||
@@ -25718,6 +25742,11 @@ impl View for Workspace {
|
||||
if WarpDriveSettings::is_warp_drive_enabled(app) {
|
||||
context.set.insert(flags::ENABLE_WARP_DRIVE);
|
||||
}
|
||||
if FeatureFlag::GalaxyControlCli.is_enabled()
|
||||
&& LocalControlSettings::as_ref(app).is_enabled()
|
||||
{
|
||||
context.set.insert(flags::GALAXY_CONTROL_ENABLED);
|
||||
}
|
||||
|
||||
if AISettings::as_ref(app).is_any_ai_enabled(app)
|
||||
&& *AISettings::as_ref(app).show_conversation_history
|
||||
|
||||
Reference in New Issue
Block a user