feat: expand Galaxy agent and remote tooling

Add Wormhole remote helpers, provider and agent improvements, filesystem diagnostics, model metadata support, and schema-aware settings IntelliSense.
This commit is contained in:
2026-08-23 13:55:47 -05:00
parent f17642fc62
commit 7c106eecd5
147 changed files with 2208 additions and 1514 deletions
+20 -6
View File
@@ -152,7 +152,19 @@ impl RemoteTransport for SshTransport {
fn check_binary(&self) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send>> {
let socket_path = self.socket_path.clone();
Box::pin(async move {
let cmd = remote_server::setup::binary_check_command();
let binary = remote_server::setup::remote_server_binary();
let expected_helper_version = if remote_server::setup::uses_static_linux_helper() {
let platform = detect_remote_platform(&socket_path).await?;
installation::local_helper_version(&platform).await
} else {
None
};
let cmd = match expected_helper_version {
Some(version) => format!(
"{binary} --version >/dev/null && test \"$(cat {binary}.wormhole-version 2>/dev/null)\" = \"{version}\""
),
None => remote_server::setup::binary_check_command(),
};
log::info!("Running binary check: {cmd}");
let output = remote_server::ssh::run_ssh_command(
&socket_path,
@@ -161,16 +173,18 @@ impl RemoteTransport for SshTransport {
)
.await?;
// `<binary> --version` exits 0 when present, executable, and
// functional. Exit 127 means the binary was not found, and 126
// means it exists but is not executable. Any other non-zero
// exit (e.g. SSH exit 255 for a dead connection, or signal
// termination) is treated as a transport-level failure.
// functional. Static helpers additionally compare their bundled
// build marker, where exit 1 means the remote copy is stale.
// Exit 127 means the binary was not found, and 126 means it exists
// but is not executable. Any other non-zero exit (e.g. SSH exit
// 255 for a dead connection, or signal termination) is treated as
// a transport-level failure.
let code = output.status.code();
let stdout = String::from_utf8_lossy(&output.stdout);
log::info!("Binary check result: exit={code:?} stdout={stdout}");
match code {
Some(0) => Ok(true),
Some(126) | Some(127) => Ok(false),
Some(1) | Some(126) | Some(127) => Ok(false),
Some(code) => {
let stderr = String::from_utf8_lossy(&output.stderr);
Err(Error::Other(anyhow::anyhow!(
@@ -4,6 +4,8 @@ mod scp_fallback;
use std::path::Path;
use anyhow::Result;
use galaxy_core::channel::{Channel, ChannelState};
use remote_server::setup::RemotePlatform;
use remote_server::ssh::SshCommandError;
use remote_server::transport::{Error, InstallOutcome, InstallSource};
@@ -13,28 +15,38 @@ use remote_server::transport::{Error, InstallOutcome, InstallSource};
pub(super) async fn install_binary(socket_path: &Path) -> InstallOutcome {
let binary_path = remote_server::setup::remote_server_binary();
log::info!("Installing remote server binary to {binary_path}");
let mut outcome = match install_on_server(socket_path).await {
Ok(()) => InstallOutcome {
source: Some(InstallSource::Server),
result: Ok(()),
},
Err(server_err) => {
if scp_fallback::should_try_install(&server_err) {
log::info!("Remote server install failed; falling back to SCP upload");
match scp_fallback::install(socket_path).await {
Ok(()) => InstallOutcome {
source: Some(InstallSource::Client),
result: Ok(()),
},
Err(e) => InstallOutcome {
source: Some(InstallSource::Client),
result: Err(e),
},
}
} else {
InstallOutcome {
source: Some(InstallSource::Server),
result: Err(server_err),
let mut outcome = if matches!(ChannelState::channel(), Channel::Local | Channel::Oss) {
// Local-first builds never contact Warp's release service. Their
// statically linked Linux helpers are bundled with Galaxy and copied
// through the SSH connection instead.
InstallOutcome {
source: Some(InstallSource::Client),
result: scp_fallback::install_local_helper(socket_path).await,
}
} else {
match install_on_server(socket_path).await {
Ok(()) => InstallOutcome {
source: Some(InstallSource::Server),
result: Ok(()),
},
Err(server_err) => {
if scp_fallback::should_try_install(&server_err) {
log::info!("Remote server install failed; falling back to SCP upload");
match scp_fallback::install(socket_path).await {
Ok(()) => InstallOutcome {
source: Some(InstallSource::Client),
result: Ok(()),
},
Err(e) => InstallOutcome {
source: Some(InstallSource::Client),
result: Err(e),
},
}
} else {
InstallOutcome {
source: Some(InstallSource::Server),
result: Err(server_err),
}
}
}
}
@@ -73,6 +85,13 @@ pub(super) async fn install_binary(socket_path: &Path) -> InstallOutcome {
outcome
}
/// Returns the build marker for the static helper bundled for `platform`, if
/// this client has one. The SSH transport uses this to avoid copying the helper
/// when the matching build is already installed remotely.
pub(super) async fn local_helper_version(platform: &RemotePlatform) -> Option<String> {
scp_fallback::local_helper_version(platform).await
}
/// Runs the install script on the remote host to download and install the
/// binary directly from the CDN.
async fn install_on_server(socket_path: &Path) -> Result<(), Error> {
@@ -8,6 +8,9 @@ use remote_server::setup::RemotePlatform;
use remote_server::transport::Error;
const REMOTE_SERVER_TARBALL_CACHE_FILE_NAME: &str = "oz.tar.gz";
const WORMHOLE_HELPER_TARBALL_FILE_NAME: &str = "galaxy-wormhole.tar.gz";
const WORMHOLE_HELPER_VERSION_FILE_NAME: &str = "galaxy-wormhole.version";
const WORMHOLE_HELPERS_DIR_ENV: &str = "GALAXY_WORMHOLE_HELPERS_DIR";
const REMOTE_SERVER_TARBALL_DOWNLOAD_ATTEMPTS: usize = 3;
// The local SCP fallback download can run over slow or captive networks. Match
@@ -25,6 +28,29 @@ pub(super) fn should_try_install(error: &Error) -> bool {
!matches!(error, Error::ScriptFailed { exit_code, .. } if *exit_code == 2)
}
/// Installs the static Linux helper shipped with local-first Galaxy builds.
/// No network download is attempted: the selected artifact is copied directly
/// through the existing SSH control connection.
pub(super) async fn install_local_helper(socket_path: &Path) -> Result<(), Error> {
let platform = super::super::detect_remote_platform(socket_path).await?;
let client_tarball_path = local_helper_tarball(&platform).ok_or_else(|| {
Error::Other(anyhow::anyhow!(
"Galaxy does not contain a Wormhole helper for Linux {}. Expected {} under the bundled resources or {}.",
platform.arch.as_str(),
helper_relative_path(&platform)
.map(|path| path.display().to_string())
.unwrap_or_else(|| "a supported Linux platform directory".to_string()),
WORMHOLE_HELPERS_DIR_ENV,
))
})?;
log::info!(
"Using bundled Wormhole helper at {}",
client_tarball_path.display()
);
install_tarball(socket_path, &client_tarball_path).await
}
/// Installs the remote server via SCP fallback.
///
/// The tarball is downloaded or reused from the local cache first, then uploaded
@@ -36,6 +62,10 @@ pub(super) async fn install(socket_path: &Path) -> Result<(), Error> {
let client_tarball_path = cached_remote_server_tarball(&platform)
.await
.map_err(Error::Other)?;
install_tarball(socket_path, &client_tarball_path).await
}
async fn install_tarball(socket_path: &Path, client_tarball_path: &Path) -> Result<(), Error> {
let timeout = remote_server::setup::SCP_INSTALL_TIMEOUT;
let install_dir = remote_server::setup::remote_server_dir();
let remote_tarball_name = format!("oz-upload-{}.tar.gz", uuid::Uuid::new_v4());
@@ -63,7 +93,7 @@ pub(super) async fn install(socket_path: &Path) -> Result<(), Error> {
log::info!("Uploading tarball to remote at {remote_tarball_path}");
remote_server::ssh::scp_upload(
socket_path,
&client_tarball_path,
client_tarball_path,
&remote_tarball_path,
timeout,
)
@@ -88,6 +118,58 @@ pub(super) async fn install(socket_path: &Path) -> Result<(), Error> {
}
}
fn helper_relative_path(platform: &RemotePlatform) -> Option<PathBuf> {
if !matches!(&platform.os, remote_server::setup::RemoteOs::Linux) {
return None;
}
Some(
PathBuf::from(format!("linux-{}", platform.arch.as_str()))
.join(WORMHOLE_HELPER_TARBALL_FILE_NAME),
)
}
fn helper_roots() -> Vec<PathBuf> {
let mut roots = Vec::new();
if let Some(path) = std::env::var_os(WORMHOLE_HELPERS_DIR_ENV) {
roots.push(path.into());
}
if let Some(resources_dir) = galaxy_core::paths::bundled_resources_dir() {
roots.push(resources_dir.join("wormhole-helpers"));
}
if cfg!(debug_assertions) {
roots.push(
Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.expect("app manifest directory should have a workspace parent")
.join("resources")
.join("wormhole-helpers"),
);
}
roots
}
fn local_helper_tarball(platform: &RemotePlatform) -> Option<PathBuf> {
let relative_path = helper_relative_path(platform)?;
helper_roots()
.into_iter()
.map(|root| root.join(&relative_path))
.find(|path| {
std::fs::metadata(path).is_ok_and(|metadata| metadata.is_file() && metadata.len() > 0)
})
}
pub(super) async fn local_helper_version(platform: &RemotePlatform) -> Option<String> {
let tarball = local_helper_tarball(platform)?;
let version_path = tarball.parent()?.join(WORMHOLE_HELPER_VERSION_FILE_NAME);
let version = async_fs::read_to_string(version_path).await.ok()?;
let version = version.trim();
if version.is_empty() || !version.chars().all(|c| c.is_ascii_hexdigit()) {
return None;
}
Some(version.to_owned())
}
fn remote_server_tarball_cache_root() -> PathBuf {
galaxy_core::paths::cache_dir()
.join("remote-server")
@@ -124,6 +206,11 @@ async fn is_valid_cached_tarball(path: &Path) -> bool {
/// Reuses an existing cached tarball when available; otherwise downloads the
/// tarball into the cache and returns the newly cached path.
async fn cached_remote_server_tarball(platform: &RemotePlatform) -> anyhow::Result<PathBuf> {
if let Some(path) = local_helper_tarball(platform) {
log::info!("Using bundled Wormhole helper at {}", path.display());
return Ok(path);
}
let cache_path = remote_server_tarball_cache_path(platform);
if is_valid_cached_tarball(&cache_path).await {
log::info!(