#!/usr/bin/env node import assert from "node:assert/strict"; import { execFile } from "node:child_process"; import { constants } from "node:fs"; import { access, lstat, mkdtemp, readFile, realpath, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { isAbsolute, join, relative } from "node:path"; import { promisify } from "node:util"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; const execFileAsync = promisify(execFile); const EXPECTED_TOOLS = ["overview", "list_threads", "inspect_thread", "wait_for_change"]; const PACKAGE_NAME = "@bodicsek/codex-chief-of-staff"; const BIN_NAME = "codex-chief-of-staff"; const DEFAULT_CACHE = "/private/tmp/codex-chief-of-staff-npm-cache"; const USAGE = "usage: npm run verify:git-package -- #"; function selectedGitPackage(argv) { if (argv.length !== 1) throw new Error(USAGE); const packageSpec = argv[0]; const fragmentAt = packageSpec.lastIndexOf("#"); const repository = packageSpec.slice(0, fragmentAt); const revision = packageSpec.slice(fragmentAt + 1); const supportedRepository = /^(?:git\+https|git\+ssh|git\+file):\/\/.+\.git$/.test(repository); const immutableRevision = /^(?:[0-9a-fA-F]{40}|v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/.test(revision); if (fragmentAt <= 0 || !supportedRepository || !immutableRevision) { throw new Error("Git package must use a supported URL pinned to a full commit or release tag"); } return { packageSpec, revision }; } function isWithin(parent, child) { const pathFromParent = relative(parent, child); return pathFromParent === "" || (!pathFromParent.startsWith("..") && !isAbsolute(pathFromParent)); } function commandExit(error) { return typeof error === "object" && error !== null && "code" in error ? String(error.code) : "unknown"; } async function installPackage(prefix, cache, packageSpec) { try { await execFileAsync("npm", [ "install", "--global", "--prefix", prefix, "--ignore-scripts", "--cache", cache, packageSpec, ], { maxBuffer: 10 * 1024 * 1024 }); } catch (error) { throw new Error(`isolated npm installation failed with exit code ${commandExit(error)}`); } } async function installedPackage(prefix, cache) { const packageRoot = join(prefix, "lib", "node_modules", PACKAGE_NAME); const executable = join(prefix, "bin", BIN_NAME); await access(executable, constants.X_OK); const packageMetadata = await lstat(packageRoot); if (packageMetadata.isSymbolicLink()) { throw new Error("installed package must not be a temporary link"); } const [realPrefix, realCache, realPackage, realExecutable] = await Promise.all([ realpath(prefix), realpath(cache), realpath(packageRoot), realpath(executable), ]); if (!isWithin(realPrefix, realPackage) || isWithin(realCache, realPackage)) { throw new Error("installed package resolved outside the isolated prefix"); } if (!isWithin(realPackage, realExecutable) || isWithin(realCache, realExecutable)) { throw new Error("installed executable resolved outside the installed package"); } const manifest = JSON.parse(await readFile(join(realPackage, "package.json"), "utf8")); assert.equal(manifest.name, PACKAGE_NAME); assert.deepEqual(manifest.bin, { [BIN_NAME]: "dist/src/index.js" }); return { executable, version: String(manifest.version) }; } async function verify() { const { packageSpec, revision } = selectedGitPackage(process.argv.slice(2)); const prefix = await mkdtemp(join(tmpdir(), "codex-chief-of-staff-git-package-")); const cache = process.env.CODEX_CHIEF_OF_STAFF_NPM_CACHE ?? DEFAULT_CACHE; let client; try { await installPackage(prefix, cache, packageSpec); const installed = await installedPackage(prefix, cache); client = new Client({ name: "git-package-verifier", version: "1.0.0" }); const transport = new StdioClientTransport({ command: installed.executable, env: { ...process.env, CODEX_APP_SERVER_URL: process.env.CODEX_APP_SERVER_URL ?? "ws://127.0.0.1:4500", }, }); await client.connect(transport); assert.match(client.getInstructions() ?? "", /call overview first/i); const listed = await client.listTools(); assert.deepEqual(listed.tools.map(({ name }) => name), EXPECTED_TOOLS); process.stdout.write(`${JSON.stringify({ ok: true, package: `${PACKAGE_NAME}@${installed.version}`, revision, executable: `bin/${BIN_NAME}`, storage: "isolated-prefix", instructions: "verified", tools: EXPECTED_TOOLS, })}\n`); } finally { if (client !== undefined) await client.close().catch(() => undefined); await rm(prefix, { recursive: true, force: true }); } } verify().catch((error) => { const message = error instanceof Error ? error.message : String(error); process.stderr.write(`Git-package verification failed: ${message}\n`); process.exitCode = 1; });