Merge 82e838bad8 into 28f8d00e9f
This commit is contained in:
commit
550d523fca
@ -12,6 +12,7 @@ import {
|
|||||||
hasBinary,
|
hasBinary,
|
||||||
loadWorkspaceSkillEntries,
|
loadWorkspaceSkillEntries,
|
||||||
resolveSkillsInstallPreferences,
|
resolveSkillsInstallPreferences,
|
||||||
|
resolveRuntimePlatform,
|
||||||
type SkillEntry,
|
type SkillEntry,
|
||||||
type SkillInstallSpec,
|
type SkillInstallSpec,
|
||||||
type SkillsInstallPreferences,
|
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> {
|
async function resolveBrewBinDir(timeoutMs: number, brewExe?: string): Promise<string | undefined> {
|
||||||
const exe = brewExe ?? (hasBinary("brew") ? "brew" : resolveBrewExecutable());
|
const exe = brewExe ?? (hasBinary("brew") ? "brew" : resolveBrewExecutable());
|
||||||
if (!exe) return undefined;
|
if (!exe) return undefined;
|
||||||
@ -366,10 +389,21 @@ export async function installSkill(params: SkillInstallRequest): Promise<SkillIn
|
|||||||
code: brewResult.code,
|
code: brewResult.code,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
} else if (resolveRuntimePlatform() === "win32" && 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 {
|
} else {
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
message: "uv not installed (install via brew)",
|
message: "uv not installed (install via brew or winget)",
|
||||||
stdout: "",
|
stdout: "",
|
||||||
stderr: "",
|
stderr: "",
|
||||||
code: null,
|
code: null,
|
||||||
@ -404,10 +438,21 @@ export async function installSkill(params: SkillInstallRequest): Promise<SkillIn
|
|||||||
code: brewResult.code,
|
code: brewResult.code,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
} else if (resolveRuntimePlatform() === "win32" && 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 {
|
} else {
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
message: "go not installed (install via brew)",
|
message: "go not installed (install via brew or winget)",
|
||||||
stdout: "",
|
stdout: "",
|
||||||
stderr: "",
|
stderr: "",
|
||||||
code: null,
|
code: null,
|
||||||
|
|||||||
@ -77,13 +77,17 @@ export function isBundledSkillAllowed(entry: SkillEntry, allowlist?: string[]):
|
|||||||
export function hasBinary(bin: string): boolean {
|
export function hasBinary(bin: string): boolean {
|
||||||
const pathEnv = process.env.PATH ?? "";
|
const pathEnv = process.env.PATH ?? "";
|
||||||
const parts = pathEnv.split(path.delimiter).filter(Boolean);
|
const parts = pathEnv.split(path.delimiter).filter(Boolean);
|
||||||
|
const extensions = process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""];
|
||||||
|
|
||||||
for (const part of parts) {
|
for (const part of parts) {
|
||||||
const candidate = path.join(part, bin);
|
for (const ext of extensions) {
|
||||||
try {
|
const candidate = path.join(part, bin + ext);
|
||||||
fs.accessSync(candidate, fs.constants.X_OK);
|
try {
|
||||||
return true;
|
fs.accessSync(candidate, fs.constants.X_OK);
|
||||||
} catch {
|
return true;
|
||||||
// keep scanning
|
} catch {
|
||||||
|
// keep scanning
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
// formatter fix
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { parseDurationMs } from "../cli/parse-duration.js";
|
import { parseDurationMs } from "../cli/parse-duration.js";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user