Merge pull request #303597 from microsoft/connor4312/agent-host-server-fixups

agentHost: fixup build for server
This commit is contained in:
Connor Peet
2026-03-20 13:54:33 -07:00
committed by GitHub
parent 79d5a79218
commit b7462b4a00
5 changed files with 51 additions and 15 deletions

View File

@@ -120,6 +120,9 @@ jobs:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: ✍️ Codesign
- powershell: Remove-Item -Path "$(Build.ArtifactStagingDirectory)/sign/CodeSignSummary*.md" -Force -ErrorAction SilentlyContinue
displayName: Remove CodeSignSummary
- task: ArchiveFiles@2
displayName: Archive signed CLI
inputs:

View File

@@ -129,6 +129,7 @@ const serverEntryPoints = [
'vs/workbench/api/node/extensionHostProcess',
'vs/platform/files/node/watcher/watcherMain',
'vs/platform/terminal/node/ptyHostMain',
'vs/platform/agentHost/node/agentHostMain',
];
// Bootstrap files per target

View File

@@ -21,7 +21,7 @@ use crate::constants::VSCODE_CLI_QUALITY;
use crate::download_cache::DownloadCache;
use crate::log;
use crate::options::Quality;
use crate::tunnels::paths::SERVER_FOLDER_NAME;
use crate::tunnels::paths::{get_server_folder_name, SERVER_FOLDER_NAME};
use crate::tunnels::shutdown_signal::ShutdownRequest;
use crate::update_service::{
unzip_downloaded_release, Platform, Release, TargetKind, UpdateService,
@@ -74,8 +74,13 @@ pub async fn agent_host(ctx: CommandContext, mut args: AgentHostArgs) -> Result<
// Eagerly resolve the latest version so the first connection is fast.
// Skip when using a dev override since updates don't apply.
if option_env!("VSCODE_CLI_OVERRIDE_SERVER_PATH").is_none() {
if let Err(e) = manager.get_latest_release().await {
warning!(ctx.log, "Error resolving initial server version: {}", e);
match manager.get_latest_release().await {
Ok(release) => {
if let Err(e) = manager.ensure_downloaded(&release).await {
warning!(ctx.log, "Error downloading latest server version: {}", e);
}
}
Err(e) => warning!(ctx.log, "Error resolving initial server version: {}", e),
}
// Start background update checker
@@ -253,9 +258,12 @@ impl AgentHostManager {
cmd.stdin(std::process::Stdio::null());
cmd.stderr(std::process::Stdio::piped());
cmd.stdout(std::process::Stdio::piped());
cmd.arg("--socket-path");
cmd.arg(get_socket_name());
cmd.arg("--agent-host-path");
cmd.arg(&agent_host_socket);
cmd.args([
"--start-server",
"--accept-server-license-terms",
"--enable-remote-auto-shutdown",
]);
@@ -394,7 +402,8 @@ impl AgentHostManager {
// Best case: the latest known release is already downloaded
if let Some((_, release)) = &*self.latest_release.lock().await {
if let Some(dir) = self.cache.exists(&release.commit) {
let name = get_server_folder_name(release.quality, &release.commit);
if let Some(dir) = self.cache.exists(&name) {
return Ok((release.clone(), dir));
}
}
@@ -405,15 +414,23 @@ impl AgentHostManager {
Quality::try_from(q).map_err(|_| CodeError::UpdatesNotConfigured("unknown quality"))
})?;
// Fall back to any cached version (still instant, just not the newest)
for commit in self.cache.get() {
if let Some(dir) = self.cache.exists(&commit) {
// Fall back to any cached version (still instant, just not the newest).
// Cache entries are named "<quality>-<commit>" via get_server_folder_name.
for entry in self.cache.get() {
if let Some(dir) = self.cache.exists(&entry) {
let (entry_quality, commit) = match entry.split_once('-') {
Some((q, c)) => match Quality::try_from(q.to_lowercase().as_str()) {
Ok(parsed) => (parsed, c.to_string()),
Err(_) => (quality, entry.clone()),
},
None => (quality, entry.clone()),
};
let release = Release {
name: String::new(),
commit,
platform: self.platform,
target: TargetKind::Server,
quality,
quality: entry_quality,
};
return Ok((release, dir));
}
@@ -428,7 +445,8 @@ impl AgentHostManager {
/// Ensures the release is downloaded, returning the server directory.
async fn ensure_downloaded(&self, release: &Release) -> Result<PathBuf, CodeError> {
if let Some(dir) = self.cache.exists(&release.commit) {
let cache_name = get_server_folder_name(release.quality, &release.commit);
if let Some(dir) = self.cache.exists(&cache_name) {
return Ok(dir);
}
@@ -436,9 +454,8 @@ impl AgentHostManager {
let release = release.clone();
let log = self.log.clone();
let update_service = self.update_service.clone();
let commit = release.commit.clone();
self.cache
.create(&commit, |target_dir| async move {
.create(&cache_name, |target_dir| async move {
let tmpdir = tempfile::tempdir().unwrap();
let response = update_service.get_download_stream(&release).await?;
let name = response.url_path_basename().unwrap();
@@ -449,7 +466,8 @@ impl AgentHostManager {
response,
)
.await?;
unzip_downloaded_release(&archive_path, &target_dir, SilentCopyProgress())?;
let server_dir = target_dir.join(SERVER_FOLDER_NAME);
unzip_downloaded_release(&archive_path, &server_dir, SilentCopyProgress())?;
Ok(())
})
.await
@@ -504,7 +522,8 @@ impl AgentHostManager {
};
// Check if we already have this version
if self.cache.exists(&new_release.commit).is_some() {
let name = get_server_folder_name(new_release.quality, &new_release.commit);
if self.cache.exists(&name).is_some() {
continue;
}
@@ -562,7 +581,10 @@ async fn handle_request(
let rw = match get_socket_rw_stream(&socket_path).await {
Ok(rw) => rw,
Err(e) => {
error!(manager.log, "Error connecting to agent host socket: {:?}", e);
error!(
manager.log,
"Error connecting to agent host socket: {:?}", e
);
return Ok(Response::builder()
.status(503)
.body(Body::from(format!("Error connecting to agent host: {e:?}")))

View File

@@ -24,6 +24,7 @@ export interface NativeParsedArgs {
};
};
'serve-web'?: INativeCliOptions;
'agent-host'?: INativeCliOptions;
chat?: {
_: string[];
'add-file'?: string[];

View File

@@ -45,7 +45,7 @@ export type OptionDescriptions<T> = {
Subcommand<T[P]>
};
export const NATIVE_CLI_COMMANDS = ['tunnel', 'serve-web'] as const;
export const NATIVE_CLI_COMMANDS = ['tunnel', 'serve-web', 'agent-host'] as const;
export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'chat': {
@@ -71,6 +71,15 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'telemetry-level': { type: 'string' },
}
},
'agent-host': {
type: 'subcommand',
description: 'Run a server that hosts agents.',
options: {
'cli-data-dir': { type: 'string', args: 'dir', description: localize('cliDataDir', "Directory where CLI metadata should be stored.") },
'disable-telemetry': { type: 'boolean' },
'telemetry-level': { type: 'string' },
}
},
'tunnel': {
type: 'subcommand',
description: 'Make the current machine accessible from vscode.dev or other machines through a secure tunnel.',