Ctrl K
ComunidadGuías…

scripts/agent-release.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { createHash } from "node:crypto";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import {
  agentReleasePlatforms,
  validateAgentRelease,
} from "../app/src/lib/agent-release.mjs";

const root = resolve(import.meta.dirname, "..");
export function manifestForBinaries({
  version,
  repository,
  goVersion,
  metadata,
  binaries,
}) {
  if (metadata.version !== version)
    throw new Error(
      "Agent build version does not match the application version.",
    );
  const assets = agentReleasePlatforms.map((platform) => {
    const body = binaries.get(platform.filename);
    // Verify the executable platform, not merely a filename supplied by a caller.
    if (
      !body ||
      body.length < 64 ||
      body.subarray(0, 4).toString("hex") !== "7f454c46" ||
      body[4] !== 2 ||
      body[5] !== 1 ||
      ![0, 3].includes(body[7]) ||
      body.readUInt16LE(16) !== 2 ||
      body.readUInt16LE(18) !== (platform.arch === "amd64" ? 62 : 183)
    )
      throw new Error(`Invalid ELF platform: ${platform.filename}`);
    return {
      ...platform,
      size: body.length,
      sha256: createHash("sha256").update(body).digest("hex"),
      url: `https://github.com/${repository}/releases/download/v${version}/${platform.filename}`,
    };
  });
  return validateAgentRelease({
    schemaVersion: 1,
    version,
    repository,
    goVersion,
    protocolVersion: metadata.protocolVersion,
    capabilities: metadata.capabilities,
    assets,
  });
}
function run(command, args, extra = {}) {
  const result = spawnSync(command, args, {
    cwd: root,
    env: { ...process.env, ...extra },
    encoding: "utf8",
  });
  if (result.error) throw result.error;
  if (result.status !== 0)
    throw new Error(`${command} failed: ${result.stderr}`);
  return result.stdout;
}
export function prepareAgentRelease({
  directory = resolve(root, "bin"),
  manifestPath = resolve(root, "app/agent-release.json"),
} = {}) {
  const { version, repository } = JSON.parse(
    readFileSync(resolve(root, "app/package.json"), "utf8"),
  );
  const repositoryUrl =
    typeof repository === "string" ? repository : repository?.url;
  const repositoryName = /github\.com[/:]([^/]+\/[^/]+?)(?:\.git)?$/.exec(
    repositoryUrl ?? "",
  )?.[1];
  if (!repositoryName)
    throw new Error("Application package must identify its GitHub repository.");
  mkdirSync(directory, { recursive: true });
  for (const platform of agentReleasePlatforms)
    run(
      process.execPath,
      ["scripts/build-agent.mjs", resolve(directory, platform.filename)],
      { GOOS: platform.os, GOARCH: platform.arch },
    );
  const native = resolve(root, ".tmp/agent-release/native-agent");
  run(process.execPath, ["scripts/build-agent.mjs", native], {
    GOOS: process.platform === "darwin" ? "darwin" : process.platform,
    GOARCH: process.arch === "arm64" ? "arm64" : "amd64",
  });
  const metadata = JSON.parse(run(native, ["version", "--json"]));
  const goVersion = run("go", ["env", "GOVERSION"]).trim();
  const binaries = new Map(
    agentReleasePlatforms.map(({ filename }) => [
      filename,
      readFileSync(resolve(directory, filename)),
    ]),
  );
  const manifest = manifestForBinaries({
    version,
    repository: repositoryName,
    goVersion,
    metadata,
    binaries,
  });
  mkdirSync(dirname(manifestPath), { recursive: true });
  const json = JSON.stringify(manifest, null, 2) + "\n";
  writeFileSync(manifestPath, json);
  writeFileSync(resolve(directory, "agent-release.json"), json);
  writeFileSync(
    resolve(directory, "SHA256SUMS"),
    manifest.assets
      .map((asset) => `${asset.sha256}  ${asset.filename}`)
      .join("\n") + "\n",
  );
  console.log(
    `Prepared agent ${version}: Linux amd64/arm64 and verified manifest.`,
  );
  return manifest;
}
if (
  process.argv[1] &&
  resolve(process.argv[1]) === fileURLToPath(import.meta.url)
) {
  const args = process.argv.slice(2);
  if (args.length > 2)
    throw new Error(
      "Usage: node scripts/agent-release.mjs [output-directory] [manifest-path]",
    );
  prepareAgentRelease({
    ...(args[0] ? { directory: resolve(args[0]) } : {}),
    ...(args[1] ? { manifestPath: resolve(args[1]) } : {}),
  });
}