chore: set goose binaries as executable in package.json (#8589)

This commit is contained in:
Jack Amadeo
2026-04-16 11:36:53 -04:00
committed by GitHub
parent fd93865951
commit 67b90205ed
15 changed files with 452 additions and 390 deletions
-103
View File
@@ -1,103 +0,0 @@
#!/usr/bin/env node
// For development: ensures the Rust binary is built from source and
// points server-binary.json to the local target/release/goose binary.
// Rebuilds if source files are newer than the binary.
import { writeFileSync, existsSync, statSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = join(__dirname, "..", "..", "..");
const binaryName = process.platform === "win32" ? "goose.exe" : "goose";
const binaryPath = join(projectRoot, "target", "release", binaryName);
// Verify we're in a development environment with Cargo.toml
const cargoToml = join(projectRoot, "Cargo.toml");
if (!existsSync(cargoToml)) {
console.error("Error: Not in a Rust workspace (Cargo.toml not found)");
console.error("This script is for development only. In production, use the prebuilt binaries.");
process.exit(1);
}
function needsRebuild() {
if (!existsSync(binaryPath)) {
console.log("Binary not found, needs build");
return true;
}
const binaryMtime = statSync(binaryPath).mtimeMs;
// Check if any Rust source files are newer than the binary
const cargoLock = join(projectRoot, "Cargo.lock");
if (existsSync(cargoToml) && statSync(cargoToml).mtimeMs > binaryMtime) {
console.log("Cargo.toml changed, needs rebuild");
return true;
}
if (existsSync(cargoLock) && statSync(cargoLock).mtimeMs > binaryMtime) {
console.log("Cargo.lock changed, needs rebuild");
return true;
}
// Check if goose-acp crate sources are newer than the binary
const acpDir = join(projectRoot, "crates", "goose-acp");
if (existsSync(acpDir)) {
const result = spawnSync(
"find",
[acpDir, "-type", "f", "(", "-name", "*.rs", "-o", "-name", "Cargo.toml", ")", "-newer", binaryPath],
{ encoding: "utf-8" },
);
const changed = (result.stdout ?? "").trim();
if (changed) {
const first = changed.split("\n")[0];
console.log(`goose-acp changed (e.g. ${first}), needs rebuild`);
return true;
}
}
return false;
}
function buildBinary() {
console.log("Building goose-cli from source...");
const result = spawnSync(
"cargo",
["build", "--release", "-p", "goose-cli"],
{
cwd: projectRoot,
stdio: "inherit",
}
);
if (result.error) {
console.error(`Failed to build: ${result.error.message}`);
process.exit(1);
}
if (result.status !== 0) {
console.error(`Build failed with exit code ${result.status}`);
process.exit(1);
}
console.log(`Built goose binary at ${binaryPath}`);
}
// Main logic
if (needsRebuild()) {
buildBinary();
} else {
console.log("Binary is up to date, skipping build");
}
// Write the server-binary.json to point to the local build
const outDir = join(__dirname, "..");
writeFileSync(
join(outDir, "server-binary.json"),
JSON.stringify({ binaryPath }, null, 2) + "\n",
);
console.log(`Using local goose binary at ${binaryPath}`);
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env node
// Development entrypoint: ensures a goose binary is available, then launches
// the TUI via tsx. Skips the cargo build if GOOSE_BINARY is already set.
import { execFileSync } from "node:child_process";
import { existsSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const repoRoot = join(__dirname, "..", "..", "..");
if (!process.env.GOOSE_BINARY) {
const binName = process.platform === "win32" ? "goose.exe" : "goose";
const binaryPath = join(repoRoot, "target", "debug", binName);
console.log("Building goose (debug)…");
execFileSync("cargo", ["build", "-p", "goose-cli"], {
cwd: repoRoot,
stdio: "inherit",
});
if (!existsSync(binaryPath)) {
console.error(`Build succeeded but binary not found at ${binaryPath}`);
process.exit(1);
}
process.env.GOOSE_BINARY = binaryPath;
}
execFileSync("tsx", [join(__dirname, "..", "src", "tui.tsx"), ...process.argv.slice(2)], {
cwd: process.cwd(),
stdio: "inherit",
env: process.env,
});
-63
View File
@@ -1,63 +0,0 @@
#!/usr/bin/env node
// Resolves the path to the goose binary from the platform-specific
// optional dependency. Writes the result to a JSON file that the CLI reads at
// startup so it can spawn the server automatically.
import { writeFileSync, mkdirSync, chmodSync } from "node:fs";
import { createRequire } from "node:module";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);
const PLATFORMS = {
"darwin-arm64": "@aaif/goose-binary-darwin-arm64",
"darwin-x64": "@aaif/goose-binary-darwin-x64",
"linux-arm64": "@aaif/goose-binary-linux-arm64",
"linux-x64": "@aaif/goose-binary-linux-x64",
"win32-x64": "@aaif/goose-binary-win32-x64",
};
const key = `${process.platform}-${process.arch}`;
const pkg = PLATFORMS[key];
if (!pkg) {
console.warn(
`@aaif/goose: no prebuilt goose binary for ${key}. ` +
`You will need to provide a server URL manually with --server.`,
);
process.exit(0);
}
let binaryPath;
try {
// Resolve the package directory, then point at the binary inside it
const pkgDir = dirname(require.resolve(`${pkg}/package.json`));
const binName = process.platform === "win32" ? "goose.exe" : "goose";
binaryPath = join(pkgDir, "bin", binName);
} catch {
// The optional dependency wasn't installed (e.g. wrong platform). That's fine.
console.warn(
`@aaif/goose: optional dependency ${pkg} not installed. ` +
`You will need to provide a server URL manually with --server.`,
);
process.exit(0);
}
// Ensure the binary is executable (npm may strip permissions during packaging)
if (process.platform !== "win32") {
try {
chmodSync(binaryPath, 0o755);
} catch {}
}
const outDir = join(__dirname, "..");
mkdirSync(outDir, { recursive: true });
writeFileSync(
join(outDir, "server-binary.json"),
JSON.stringify({ binaryPath }, null, 2) + "\n",
);
console.log(`@aaif/goose: found native goose binary at ${binaryPath}`);