Files
maka/scripts/prepare-deepseek-harness-toolchain.mjs
agent-radar 7be535059e
Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 19:05:14 +08:00

230 lines
10 KiB
JavaScript

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// Build the DeepSeek Harness toolchain that the Eval external subject mounts
// read-only at /opt/maka-deepseek-harness-toolchain.
//
// The harness's minimal composition pulls in two native modules — node-pty for
// the persistent shell, koffi for the filesystem and session backends — and
// node-pty publishes no Linux prebuild. The toolchain therefore cannot be
// installed on a macOS host and mounted into a linux/amd64 task container; it
// is built inside a matching container, which also supplies the pinned Node.
//
// The fingerprint is the digest of checksums.sha256, which lists every regular
// file this build put in the tree, itself and manifest.json aside. So the
// constant committed in src/toolchain-verification.ts pins the checksum
// manifest, and the manifest pins the content of every file it names. It does
// not pin the tree's closure: verification walks the manifest, not the
// directory, so a file added afterwards is neither named nor refused. That gap
// predates this arm and belongs to verifyToolchainDirectory. A fingerprint
// derived from the build inputs alone would match two different installs of
// the same version, which is exactly the drift a benchmark needs to detect.
//
// `npm i` is not reproducible, so rebuilding produces a new fingerprint. That
// is the point: re-pin it with --write and the change is visible in review.
import { execFile } from 'node:child_process';
import { createHash } from 'node:crypto';
import { createReadStream } from 'node:fs';
import { mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
import { homedir } from 'node:os';
import { dirname, join, relative, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { promisify } from 'node:util';
const execFileAsync = promisify(execFile);
const repoRoot = dirname(dirname(fileURLToPath(import.meta.url)));
const identityPath = join(repoRoot, 'packages', 'eval', 'src', 'toolchain-verification.ts');
const manifestDir = join(repoRoot, 'packages', 'eval', 'harbor', 'deepseek-harness-toolchain');
const DEEPSEEK_HARNESS_TOOLCHAIN_SPEC = {
// The task images are linux/amd64, and the native modules must match them.
platform: 'linux/amd64',
node: {
version: '22.23.2',
// The build image is the interpreter's provenance: its Node is copied into
// the toolchain rather than downloaded separately.
image: 'node:22-bookworm',
imageDigest: 'sha256:0557ac14e0d45d02ed563067b82856ca5e7aa3437fa28d98d4350ea9c3d9494a',
},
deepseekHarness: {
package: '@deepseek-ai/dsh',
version: '0.1.0-rc.6',
entrypoint: 'lib/dsh/node_modules/@deepseek-ai/dsh/lib/bin.js',
},
};
// Written into the build's own manifest, and the only thing that authorizes
// this script to remove a non-empty --out.
const TOOLCHAIN_BUILD_MARKER = 'maka-eval/prepare-deepseek-harness-toolchain';
async function prepareDeepSeekHarnessToolchain({ outputRoot, write = false } = {}) {
if (!outputRoot) throw new Error('--out is required');
const spec = DEEPSEEK_HARNESS_TOOLCHAIN_SPEC;
const root = resolve(outputRoot);
// --out is rebuilt from scratch, so it is the one destructive path here. It
// must name either nothing or a previous build of this toolchain, and never a
// directory someone works out of.
for (const reserved of [resolve('/'), repoRoot, process.cwd(), homedir()]) {
if (root === reserved) throw new Error(`--out must not be ${reserved}`);
}
// Only a directory this script produced may be removed. A `manifest.json`
// entry is not proof of that — plenty of directories have one — so the marker
// this script writes into its own manifest is what has to be found. An empty
// directory has nothing to lose and is accepted as it is.
//
// What the path is has to be established before what it contains: `readdir`
// fails the same way for a path that does not exist and for one that is a
// file, and reading the second as the first would delete the file.
const target = await stat(root).catch(() => undefined);
if (target && !target.isDirectory()) throw new Error(`--out must be a directory: ${root}`);
const existing = target ? await readdir(root) : undefined;
if (existing && existing.length > 0) {
const produced = await readFile(join(root, 'manifest.json'), 'utf8')
.then((raw) => JSON.parse(raw).producedBy === TOOLCHAIN_BUILD_MARKER)
.catch(() => false);
if (!produced) {
throw new Error(`${root} is not empty and was not produced by ${TOOLCHAIN_BUILD_MARKER}`);
}
}
// Both the lockfile and the spec name a harness version. If they disagree the
// manifest would describe something other than what was installed.
const lock = JSON.parse(await readFile(join(manifestDir, 'package-lock.json'), 'utf8'));
const locked = lock.packages?.[`node_modules/${spec.deepseekHarness.package}`]?.version;
if (locked !== spec.deepseekHarness.version) {
throw new Error(
`lockfile pins ${spec.deepseekHarness.package}@${locked}, spec says ${spec.deepseekHarness.version}`,
);
}
await rm(root, { recursive: true, force: true });
await mkdir(join(root, 'bin'), { recursive: true });
await mkdir(join(root, 'lib', 'dsh'), { recursive: true });
const image = `${spec.node.image}@${spec.node.imageDigest}`;
const install = [
// The image digest fixes the interpreter; this asserts the version the spec
// claims for it.
`test "$(node -v)" = "v${spec.node.version}"`,
// `npm ci` installs exactly the reviewed lockfile. `npm i` would re-resolve
// several hundred caret ranges, so two builds of the same harness version
// could disagree on what they actually installed.
'cp /manifest/package.json /manifest/package-lock.json .',
'npm ci >/dev/null 2>&1',
'node /manifest/patch-subprocess-local.mjs /build',
// Fail the build here rather than at benchmark time if the native module
// did not compile.
'node -e "require(\'node-pty\')"',
'cp "$(command -v node)" /out/bin/node',
'cp -R package.json package-lock.json node_modules /out/lib/dsh/',
].join(' && ');
await execFileAsync('docker', [
'run',
'--rm',
'--platform',
spec.platform,
'-v',
`${root}:/out`,
'-v',
`${manifestDir}:/manifest:ro`,
'-w',
'/build',
image,
'sh',
'-c',
install,
]);
// The entrypoint path is a shape assumption the spec and the experiment args
// both depend on; the container's `&&` chain already fails the build if the
// copies or the native module did not work.
await requireRegularFile(join(root, spec.deepseekHarness.entrypoint), 'harness entrypoint');
const checksums = await checksumTree(root);
await writeFile(join(root, 'checksums.sha256'), checksums, { mode: 0o644 });
const fingerprint = `sha256:${createHash('sha256').update(checksums).digest('hex')}`;
// `fingerprint` is provenance here, not identity: verification recomputes it
// from checksums.sha256 and never reads this file.
await writeFile(
join(root, 'manifest.json'),
`${JSON.stringify({ producedBy: TOOLCHAIN_BUILD_MARKER, fingerprint, spec }, null, 2)}\n`,
{ mode: 0o644 },
);
if (write) await recordFingerprint(fingerprint);
return { root, version: spec.deepseekHarness.version, fingerprint };
}
// Checksums cover every regular file, sorted by toolchain-relative path so the
// digest is stable across builds. manifest.json is written afterwards and is
// therefore not part of its own input.
async function checksumTree(root) {
const files = [];
await collect(root, files);
files.sort();
const lines = [];
for (const path of files) lines.push(`${await hashFile(path)} ${relative(root, path)}`);
return `${lines.join('\n')}\n`;
}
async function collect(directory, files) {
for (const entry of await readdir(directory, { withFileTypes: true })) {
const path = join(directory, entry.name);
if (entry.isDirectory()) await collect(path, files);
else if (entry.isFile()) files.push(path);
}
}
function hashFile(path) {
return new Promise((resolveHash, reject) => {
const hash = createHash('sha256');
const stream = createReadStream(path);
stream.on('data', (chunk) => hash.update(chunk));
stream.on('error', reject);
stream.on('end', () => resolveHash(hash.digest('hex')));
});
}
async function requireRegularFile(path, label) {
const info = await stat(path).catch(() => undefined);
if (!info?.isFile()) throw new Error(`${label} is missing at ${path}`);
}
async function recordFingerprint(fingerprint) {
const source = await readFile(identityPath, 'utf8');
const pattern =
/('deepseek-harness': \{\n\s*root: '[^']+',\n\s*version: ')([^']+)(',\n\s*fingerprint: ')([^']+)(')/u;
if (!pattern.test(source)) throw new Error('deepseek-harness toolchain identity was not found');
const next = source.replace(
pattern,
`$1${DEEPSEEK_HARNESS_TOOLCHAIN_SPEC.deepseekHarness.version}$3${fingerprint}$5`,
);
await writeFile(identityPath, next, 'utf8');
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
const argv = process.argv.slice(2);
const outIndex = argv.indexOf('--out');
const result = await prepareDeepSeekHarnessToolchain({
outputRoot: outIndex >= 0 ? argv[outIndex + 1] : undefined,
write: argv.includes('--write'),
});
console.log(`${result.root}\n${result.fingerprint}`);
}