Files
wehub-resource-sync 221778fa98
rowboat / apps/x Vitest suites (push) Has been cancelled
rowboat / apps/x Electron package smoke test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:33:34 +08:00

112 lines
4.8 KiB
JavaScript

// Build-time generator for the code-mode engine manifest.
//
// Code mode provisions each agent's native engine on demand by downloading the
// per-platform npm package AT THE EXACT VERSION OUR ACP ADAPTER DEPENDS ON, so the
// adapter <-> engine handshake is always in lockstep. This script reads those pinned
// versions from the installed adapter package.json files, queries the npm registry for
// each platform package's tarball URL + integrity, and writes them to
// `src/code-mode/acp/engine-manifest.ts` (committed; regenerate on a version bump).
//
// Usage: node scripts/gen-engine-manifest.mjs (run from packages/core)
//
// Why a committed .ts (not a fetched-at-build .json): it needs no network at app build
// time, works offline in dev, is reviewable in PRs, and esbuild inlines it into the
// packaged main bundle.
import { createRequire } from 'module';
import { writeFileSync } from 'fs';
import { fileURLToPath } from 'url';
import * as path from 'path';
const require = createRequire(import.meta.url);
const REGISTRY = 'https://registry.npmjs.org';
// Platform keys we publish for each agent. These mirror the optionalDependencies of the
// engine packages. claude ships musl variants; codex does not.
const CLAUDE_PLATFORMS = [
'darwin-arm64', 'darwin-x64',
'linux-x64', 'linux-arm64', 'linux-x64-musl', 'linux-arm64-musl',
'win32-x64', 'win32-arm64',
];
const CODEX_PLATFORMS = [
'darwin-arm64', 'darwin-x64',
'linux-x64', 'linux-arm64',
'win32-x64', 'win32-arm64',
];
// Read a pinned dependency version from an adapter's package.json, stripping any range
// prefix (^, ~). createRequire resolves the adapter from the installed node_modules.
function pinnedDep(adapterPkg, depName) {
const pj = require(`${adapterPkg}/package.json`);
const spec = (pj.dependencies || {})[depName] || (pj.optionalDependencies || {})[depName];
if (!spec) throw new Error(`${adapterPkg} has no dependency on ${depName}`);
return spec.replace(/^[\^~]/, '');
}
// Fetch a single version's manifest from the registry and return its dist coordinates.
async function distFor(pkg, version) {
const url = `${REGISTRY}/${pkg}/${version}`;
const res = await fetch(url);
if (!res.ok) {
if (res.status === 404) return null; // platform not published for this version
throw new Error(`registry ${res.status} for ${pkg}@${version}`);
}
const doc = await res.json();
return { tarball: doc.dist.tarball, integrity: doc.dist.integrity };
}
// Build one agent's manifest entry: { version, platforms: { <key>: {tarball, integrity} } }.
// pkgFor(platform) -> { pkg, version } gives the registry coordinates for each platform.
async function buildAgent(version, platforms, pkgFor) {
const out = { version, platforms: {} };
for (const key of platforms) {
const { pkg, version: pv } = pkgFor(key);
const dist = await distFor(pkg, pv);
if (!dist) {
console.warn(` ! ${pkg}@${pv} not found on registry — skipping ${key}`);
continue;
}
out.platforms[key] = { pkg, pkgVersion: pv, ...dist };
console.log(` ✓ ${key}: ${pkg}@${pv}`);
}
return out;
}
async function main() {
// Pinned engine versions, read straight from the adapters we ship.
const claudeVersion = pinnedDep('@agentclientprotocol/claude-agent-acp', '@anthropic-ai/claude-agent-sdk');
const codexVersion = pinnedDep('@agentclientprotocol/codex-acp', '@openai/codex');
console.log(`claude engine: @anthropic-ai/claude-agent-sdk@${claudeVersion}`);
console.log(`codex engine: @openai/codex@${codexVersion}`);
const manifest = {
claude: await buildAgent(claudeVersion, CLAUDE_PLATFORMS, (key) => ({
pkg: `@anthropic-ai/claude-agent-sdk-${key}`,
version: claudeVersion,
})),
codex: await buildAgent(codexVersion, CODEX_PLATFORMS, (key) => ({
// codex publishes platform binaries as VERSIONS of @openai/codex
// (e.g. 0.128.0-darwin-arm64), not as separate package names.
pkg: '@openai/codex',
version: `${codexVersion}-${key}`,
})),
};
const outPath = path.join(
path.dirname(fileURLToPath(import.meta.url)),
'..', 'src', 'code-mode', 'acp', 'engine-manifest.ts',
);
const banner =
'// AUTO-GENERATED by packages/core/scripts/gen-engine-manifest.mjs — do not edit by hand.\n' +
'// Regenerate after bumping the @agentclientprotocol/*-acp adapter (engine) versions.\n' +
'// Maps each agent + platform to the npm tarball + integrity of its native engine.\n\n';
const body = `export const ENGINE_MANIFEST = ${JSON.stringify(manifest, null, 4)} as const;\n`;
writeFileSync(outPath, banner + body);
console.log(`\nWrote ${outPath}`);
}
main().catch((e) => {
console.error(e);
process.exit(1);
});