mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-21 00:05:49 +02:00
fix(runner): bundle the Claude ACP runtime and explain missing packages
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
bfe7c6357d
commit
2d81789c14
19 files changed
+180
-9
No files matched your search
@@ -100,6 +100,21 @@ export async function findRunnerExternalPackages(entryPoints) {
|
||||
return externalPackageNames;
|
||||
}
|
||||
|
||||
// Provider entrypoints are resolved with createRequire from profile metadata,
|
||||
// so esbuild cannot see them. These two bridges ship in the server package;
|
||||
// other ACP agents use separately provisioned provider packs.
|
||||
export async function findRunnerRuntimePackages(entryPoints, profileData) {
|
||||
const packages = await findRunnerExternalPackages(entryPoints);
|
||||
for (const agent of ["claude", "codex"]) {
|
||||
const profile = profileData?.profiles?.[agent];
|
||||
if (profileData?.schema !== "paperclip.acpx-profiles.v1" || !profile?.agentServerPackage) {
|
||||
throw new Error(`paperclip-runner vendor check: missing ${agent} provider profile.`);
|
||||
}
|
||||
packages.add(profile.agentServerPackage);
|
||||
}
|
||||
return packages;
|
||||
}
|
||||
|
||||
function readDependencyNames(packageJsonPath) {
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
||||
return new Map(Object.entries(packageJson.dependencies ?? {}));
|
||||
@@ -125,7 +140,8 @@ function explainMissingDependencies(missing, runnerDependencyNames) {
|
||||
|
||||
async function main() {
|
||||
const entryPoints = ENTRY_POINT_NAMES.map((name) => resolve(runnerDist, name));
|
||||
const externalPackageNames = await findRunnerExternalPackages(entryPoints);
|
||||
const profileData = JSON.parse(readFileSync(resolve(runnerRoot, "acpx-profiles.json"), "utf8"));
|
||||
const externalPackageNames = await findRunnerRuntimePackages(entryPoints, profileData);
|
||||
const serverDependencyNames = readDependencyNames(resolve(serverRoot, "package.json"));
|
||||
|
||||
const missing = findMissingVendorDependencies(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
@@ -7,6 +7,7 @@ import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
findMissingVendorDependencies,
|
||||
findRunnerExternalPackages,
|
||||
findRunnerRuntimePackages,
|
||||
} from "./verify-runner-vendor-dependencies.mjs";
|
||||
|
||||
describe("findMissingVendorDependencies", () => {
|
||||
@@ -87,6 +88,15 @@ describe("findRunnerExternalPackages", () => {
|
||||
expect(externalPackageNames).toEqual(new Set(["smol-toml"]));
|
||||
});
|
||||
|
||||
it("checks dynamically resolved bundled providers even without a JavaScript import", async () => {
|
||||
const entryPoints = writeFixture();
|
||||
const profiles = JSON.parse(readFileSync(new URL("../../packages/paperclip-runner/acpx-profiles.json", import.meta.url), "utf8"));
|
||||
const packages = await findRunnerRuntimePackages(entryPoints, profiles);
|
||||
expect(findMissingVendorDependencies(packages, new Set(["smol-toml", "@agentclientprotocol/codex-acp"])))
|
||||
.toEqual(["@agentclientprotocol/claude-agent-acp"]);
|
||||
expect(packages.has("pi-acp")).toBe(false);
|
||||
});
|
||||
|
||||
it("throws a clear, actionable error when an entry point is missing", async () => {
|
||||
fixtureDir = mkdtempSync(join(tmpdir(), "paperclip-runner-vendor-fixture-"));
|
||||
const missingEntryPoint = join(fixtureDir, "index.js");
|
||||
@@ -96,3 +106,12 @@ describe("findRunnerExternalPackages", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Claude is resolved through createRequire at runtime, outside esbuild's graph.
|
||||
it("ships the qualified Claude ACP server with the vendored runner", () => {
|
||||
const server = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
||||
const profiles = JSON.parse(readFileSync(new URL("../../packages/paperclip-runner/acpx-profiles.json", import.meta.url), "utf8"));
|
||||
const claude = profiles.profiles.claude;
|
||||
expect(server.dependencies[claude.agentServerPackage]).toBe(claude.agentServerVersion);
|
||||
expect(server.bundleDependencies).toContain(claude.agentServerPackage);
|
||||
});
|
||||
Reference in new issue
Block a user