feat: Add winget support for uv and go installation on Windows

This commit is contained in:
Trent Pierce 2026-01-26 14:43:46 -06:00
parent 9e6b45faab
commit 308251c69c
2 changed files with 57 additions and 8 deletions

View File

@ -12,6 +12,7 @@ import {
hasBinary,
loadWorkspaceSkillEntries,
resolveSkillsInstallPreferences,
resolveRuntimePlatform,
type SkillEntry,
type SkillInstallSpec,
type SkillsInstallPreferences,
@ -276,6 +277,28 @@ async function installDownloadSpec(params: {
};
}
async function installWithWinget(
packageId: string,
timeoutMs: number,
): Promise<{ code: number | null; stdout: string; stderr: string }> {
if (!hasBinary("winget")) {
return { code: null, stdout: "", stderr: "winget not found" };
}
return await runCommandWithTimeout(
[
"winget",
"install",
"--id",
packageId,
"-e",
"--silent",
"--accept-source-agreements",
"--accept-package-agreements",
],
{ timeoutMs },
);
}
async function resolveBrewBinDir(timeoutMs: number, brewExe?: string): Promise<string | undefined> {
const exe = brewExe ?? (hasBinary("brew") ? "brew" : resolveBrewExecutable());
if (!exe) return undefined;
@ -366,10 +389,21 @@ export async function installSkill(params: SkillInstallRequest): Promise<SkillIn
code: brewResult.code,
};
}
} else if (resolveRuntimePlatform() === "windows" && hasBinary("winget")) {
const result = await installWithWinget("astral-sh.uv", timeoutMs);
if (result.code !== 0) {
return {
ok: false,
message: "Failed to install uv (winget)",
stdout: result.stdout.trim(),
stderr: result.stderr.trim(),
code: result.code,
};
}
} else {
return {
ok: false,
message: "uv not installed (install via brew)",
message: "uv not installed (install via brew or winget)",
stdout: "",
stderr: "",
code: null,
@ -404,10 +438,21 @@ export async function installSkill(params: SkillInstallRequest): Promise<SkillIn
code: brewResult.code,
};
}
} else if (resolveRuntimePlatform() === "windows" && hasBinary("winget")) {
const result = await installWithWinget("GoLang.Go", timeoutMs);
if (result.code !== 0) {
return {
ok: false,
message: "Failed to install go (winget)",
stdout: result.stdout.trim(),
stderr: result.stderr.trim(),
code: result.code,
};
}
} else {
return {
ok: false,
message: "go not installed (install via brew)",
message: "go not installed (install via brew or winget)",
stdout: "",
stderr: "",
code: null,

View File

@ -74,13 +74,17 @@ export function isBundledSkillAllowed(entry: SkillEntry, allowlist?: string[]):
export function hasBinary(bin: string): boolean {
const pathEnv = process.env.PATH ?? "";
const parts = pathEnv.split(path.delimiter).filter(Boolean);
const extensions = process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""];
for (const part of parts) {
const candidate = path.join(part, bin);
try {
fs.accessSync(candidate, fs.constants.X_OK);
return true;
} catch {
// keep scanning
for (const ext of extensions) {
const candidate = path.join(part, bin + ext);
try {
fs.accessSync(candidate, fs.constants.X_OK);
return true;
} catch {
// keep scanning
}
}
}
return false;