import { execFile } from "node:child_process"; import { createHash } from "node:crypto"; import { createReadStream } from "node:fs"; import { readFile, stat } from "node:fs/promises"; import { createRequire } from "node:module"; import { dirname, join } from "node:path"; import { promisify } from "node:util"; import { dbg, diagnosticKind } from "../debug.js"; import { CLAUDE_VERSION, SDK_VERSION } from "../protocol.js"; const execFileAsync = promisify(execFile); const require = createRequire(import.meta.url); /** Official per-platform binary checksums shipped inside the pinned SDK. */ interface SdkManifest { version?: unknown; platforms?: Record< string, { binary?: unknown; checksum?: unknown } | undefined >; } async function sdkManifest(): Promise { const sdkEntry = require.resolve("@anthropic-ai/claude-agent-sdk"); return JSON.parse( await readFile(join(dirname(sdkEntry), "manifest.json"), "utf8"), ) as SdkManifest; } let resolution: Promise | undefined; function platformKey(): string { dbg?.("runtime.standard.platformKey.start"); if (process.arch !== "arm64" && process.arch !== "x64") { throw new Error( `Klaus does not support ${process.platform} ${process.arch}.`, ); } if (process.platform === "darwin" || process.platform === "win32") { return `${process.platform}-${process.arch}`; } if (process.platform !== "linux") { throw new Error( `Klaus does not support ${process.platform} ${process.arch}.`, ); } const report = process.report?.getReport(); const glibc = report && typeof report === "object" ? (report as { header?: { glibcVersionRuntime?: string } }).header ?.glibcVersionRuntime : undefined; return `linux-${process.arch}${glibc ? "" : "-musl"}`; } async function sha256(path: string): Promise { const hash = createHash("sha256"); for await (const chunk of createReadStream(path)) hash.update(chunk); return hash.digest("hex"); } async function resolve(): Promise { dbg?.("runtime.standard.resolve.start"); const key = platformKey(); const packageName = `@anthropic-ai/claude-agent-sdk-${key}`; let packageJson: string; try { packageJson = require.resolve(`${packageName}/package.json`); } catch { throw new Error(`Klaus runtime ${packageName}@${SDK_VERSION} is missing.`); } const metadata = JSON.parse(await readFile(packageJson, "utf8")) as { version?: unknown; }; if (metadata.version !== SDK_VERSION) { throw new Error( `Klaus runtime ${packageName} has version ${String(metadata.version)}, expected ${SDK_VERSION}.`, ); } const manifest = await sdkManifest(); if (manifest.version !== CLAUDE_VERSION) { throw new Error( `Klaus SDK manifest declares ${String(manifest.version)}, expected ${CLAUDE_VERSION}.`, ); } const expected = manifest.platforms?.[key]?.checksum; if (typeof expected !== "string") { throw new Error(`Klaus SDK manifest has no checksum for ${key}.`); } const executable = join( dirname(packageJson), process.platform === "win32" ? "claude.exe" : "claude", ); if (!(await stat(executable)).isFile()) { throw new Error(`Klaus runtime executable is missing from ${packageName}.`); } if ((await sha256(executable)) !== expected) { throw new Error(`Klaus runtime checksum mismatch for ${key}.`); } await execFileAsync(executable, ["--version"], { timeout: 30_000, maxBuffer: 64 * 1024, }); dbg?.("runtime.standard.resolve.end"); return executable; } export function resolveStandardRuntime(): Promise { dbg?.("runtime.standard.resolveCached", { cached: Boolean(resolution) }); resolution ??= resolve().catch((error) => { dbg?.("runtime.standard.resolve.error", { kind: diagnosticKind(error), }); resolution = undefined; throw error; }); return resolution; }