Files
Julius Brussee 82864c8f4c feat: ship Caveman 2.0.0 — engine, proxy, SDKs, unified CLI
Single-commit port of the Caveman 2 tree onto the original repo history
(candidate caveman-2@88878a4 applied over main@3098342). No unrelated-history
merge; original history untouched.

Preserved v1 surfaces:
- skills/caveman/SKILL.md byte-for-byte, plus plugin mirror and caveman.skill zip
- legacy CI (Node 18/20/22 installer + Python 3.11 suites) alongside engine-ci
- cli/install.js compatibility shim forwarding to bin/install.js
- .codex/config.toml ships both hooks and codex_hooks for older Codex (#617)
- README Trendshift + Skills.sh badges and local star-history asset
- v1.10.0-pinned curl installs; benchmarks/tmp-starcharts ignore rules

Fixed for public same-repo release:
- SECURITY.md vulnerability reporting points at this repository
- release-binaries.yml publishes to this repo via job-scoped GITHUB_TOKEN
  (cross-repo PAT removed); binary-release environment still gates signing
- packages/cli/PUBLISHING.md rewritten for packages/ layout and same-repo flow
- profile-contract and provider-catalog lanes skip lane-scope gates on
  initial import so the launch PR can gate on their real validation steps
- ANNOUNCEMENT.md network claim corrected: compression is local; requests
  still go to the provider you configured

Caveman 2 stays opt-in: bin-v1.0.0 binaries and @caveman-ai/cli publish
separately after this lands and soaks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BLvb5QniwYjmcawyssQNw9
2026-08-11 16:46:10 +02:00

89 lines
3.9 KiB
JavaScript

import { test } from "node:test";
import assert from "node:assert";
import { spawnSync } from "node:child_process";
import {
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const packageRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
const packageParent = join(packageRoot, "..");
const surfaceRoot = existsSync(join(packageParent, "agents")) ? packageParent : join(packageParent, "..");
test("packed CLI injects bundled delegate before Claude and Codex startup", () => {
const workspace = mkdtempSync(join(tmpdir(), "cave-delegate-package-"));
const packDir = join(workspace, "pack");
const installDir = join(workspace, "install");
const npmEnv = { ...process.env, npm_config_cache: join(workspace, "npm-cache") };
mkdirSync(packDir, { recursive: true });
const packed = spawnSync(
"npm",
["pack", "--ignore-scripts", "--json", "--pack-destination", packDir],
{ cwd: packageRoot, env: npmEnv, encoding: "utf8", maxBuffer: 10 * 1024 * 1024 },
);
assert.equal(packed.status, 0, packed.stderr);
const metadata = JSON.parse(packed.stdout)[0];
assert.ok(
metadata.files.some((file) => file.path === "dist/caveman-delegate-mcp.mjs"),
"npm artifact must contain bundled delegate server",
);
const tarball = join(packDir, metadata.filename);
const installed = spawnSync(
"npm",
["install", "--ignore-scripts", "--no-audit", "--no-fund", "--prefix", installDir, tarball],
{ env: npmEnv, encoding: "utf8", maxBuffer: 10 * 1024 * 1024 },
);
assert.equal(installed.status, 0, installed.stderr);
const installedPackage = join(installDir, "node_modules", "@caveman-ai", "cli");
const cli = join(installedPackage, "dist", "index.js");
const delegate = join(installedPackage, "dist", "caveman-delegate-mcp.mjs");
assert.equal(existsSync(delegate), true);
assert.deepEqual(
readFileSync(delegate),
readFileSync(join(surfaceRoot, "agents", "delegate", "caveman-delegate-mcp.mjs")),
);
for (const agentId of ["claude", "codex"]) {
const home = mkdtempSync(join(tmpdir(), `cave-packed-${agentId}-home-`));
const binDir = mkdtempSync(join(tmpdir(), `cave-packed-${agentId}-bin-`));
const capture = join(home, "delegate-startup-config");
const userConfig = join(home, agentId === "codex" ? ".codex/config.toml" : ".claude.json");
const userConfigBefore = agentId === "codex" ? 'model = "gpt-5.5"\n' : '{"sentinel":"keep"}\n';
mkdirSync(dirname(userConfig), { recursive: true });
writeFileSync(userConfig, userConfigBefore);
const stub = agentId === "codex"
? '#!/bin/sh\ncp "$CODEX_HOME/config.toml" "$CAVE_DELEGATE_CAPTURE"\n'
: '#!/bin/sh\nif [ "$1" = "--plugin-dir" ] && [ -f "$2/.mcp.json" ]; then cp "$2/.mcp.json" "$CAVE_DELEGATE_CAPTURE"; fi\n';
writeFileSync(join(binDir, agentId), `${stub}exit 0\n`, { mode: 0o755 });
mkdirSync(join(home, ".caveman-cloud"), { recursive: true });
writeFileSync(
join(home, ".caveman-cloud", "config.json"),
JSON.stringify({ execute: { delegate: true }, wrap: { proxy: false, shrink: false, mcp: false, browse: false } }),
);
const env = {
...process.env,
NO_COLOR: "1",
HOME: home,
CAVEMAN_HOME: join(home, ".caveman"),
CAVE_DELEGATE_CAPTURE: capture,
CAVE_GATEWAY_URL: "http://127.0.0.1:9",
PATH: `${binDir}:${process.env.PATH}`,
};
delete env.CAVEMAN_DELEGATE_MCP;
const run = spawnSync(process.execPath, [cli, "wrap", agentId], { env, encoding: "utf8" });
assert.equal(run.status, 0, run.stderr);
assert.ok(readFileSync(capture, "utf8").includes(delegate));
assert.equal(readFileSync(userConfig, "utf8"), userConfigBefore);
assert.equal(existsSync(join(home, ".caveman", "mcp", `${agentId}.caveman-delegate.json`)), false);
}
});