Files
PaperClipAI/server/src/__tests__/adapter-registry.test.ts
T
DottaandPaperclip 59da15066a feat(runner): deliver native Kimi Code (#18391)
Deliver native Kimi Code setup, exact models, scoped credentials, verified packages and runtime packs. Preserve current upstream release attestations and restore verified same-run remote retry dispatch without weakening process ownership.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 22:26:15 -05:00

565 lines
24 KiB
TypeScript

import { probeCopilotExecutionTarget } from "../services/copilot-connection-probe.js";
import { HttpError } from "../errors.js";
import { probeAcpxClaudeInstallation, probeAcpxCursorInstallation, probeAcpxPiInstallation } from "../vendor/paperclip-runner/live/index.js";
import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
import { buildSandboxNpmInstallCommand } from "@paperclipai/adapter-utils";
import type { ServerAdapterModule } from "../adapters/index.js";
import {
detectAdapterModel,
findActiveServerAdapter,
findServerAdapter,
listAdapterModels,
registerServerAdapter,
requireServerAdapter,
unregisterServerAdapter,
} from "../adapters/index.js";
import {
resolveExternalAdapterRegistration,
setOverridePaused,
hasActiveAdapterOverride,
} from "../adapters/registry.js";
const nativeSetup = vi.hoisted(() => ({ authenticate: vi.fn() }));
vi.mock("../services/native-runtime/setup-readiness.js", () => ({
testNativeRunnerAuthentication: nativeSetup.authenticate,
}));
vi.mock("../services/copilot-connection-probe.js",()=>({probeCopilotExecutionTarget:vi.fn(async()=>({status:"verified",models:[{id:"gpt-5.6-luna"}]}))}));
vi.mock("../vendor/paperclip-runner/live/index.js", () => ({
probeAcpxClaudeInstallation: vi.fn(async () => undefined),
probeAcpxGrokInstallation: vi.fn(async () => undefined),
probeAcpxPiInstallation: vi.fn(async () => undefined),
probeAcpxCursorInstallation: vi.fn(async () => undefined),
probeAcpxKimiInstallation: vi.fn(async () => undefined),
probeKimiModels: vi.fn(async () => undefined),
}));
it("advertises tool-refresh recovery for the selected legacy harness", () => {
for (const type of ["claude_local", "codex_local", "grok_local", "gemini_local", "kimi_local", "cursor", "opencode_local", "pi_local"]) {
expect(requireServerAdapter(type).supportsToolRefreshOnResume).toBe(true);
expect(requireServerAdapter(type).sessionManagement?.supportsSessionResume).toBe(true);
}
expect(requireServerAdapter("process").supportsToolRefreshOnResume).toBeUndefined();
});
const externalAdapter: ServerAdapterModule = {
type: "external_test",
execute: async () => ({
exitCode: 0,
signal: null,
timedOut: false,
}),
testEnvironment: async () => ({
adapterType: "external_test",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
models: [{ id: "external-model", label: "External Model" }],
supportsLocalAgentJwt: false,
};
describe("server adapter registry", () => {
beforeEach(() => {
unregisterServerAdapter("external_test");
unregisterServerAdapter("hermes_local");
unregisterServerAdapter("hermes_gateway");
unregisterServerAdapter("claude_local");
setOverridePaused("claude_local", false);
});
afterEach(() => {
unregisterServerAdapter("external_test");
unregisterServerAdapter("hermes_local");
unregisterServerAdapter("hermes_gateway");
unregisterServerAdapter("claude_local");
setOverridePaused("claude_local", false);
});
it("registers external adapters and exposes them through lookup helpers", async () => {
expect(findServerAdapter("external_test")).toBeNull();
registerServerAdapter(externalAdapter);
expect(requireServerAdapter("external_test")).toBe(externalAdapter);
expect(await listAdapterModels("external_test")).toEqual([
{ id: "external-model", label: "External Model" },
]);
});
it("removes external adapters when unregistered", () => {
registerServerAdapter(externalAdapter);
unregisterServerAdapter("external_test");
expect(findServerAdapter("external_test")).toBeNull();
expect(() => requireServerAdapter("external_test")).toThrow(
"Unknown adapter type: external_test",
);
});
it("allows external plugin to override a built-in adapter type", () => {
// claude_local is always built-in
const builtIn = findServerAdapter("claude_local");
expect(builtIn).not.toBeNull();
const plugin: ServerAdapterModule = {
type: "claude_local",
execute: async () => ({
exitCode: 0,
signal: null,
timedOut: false,
}),
testEnvironment: async () => ({
adapterType: "claude_local",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
models: [{ id: "plugin-model", label: "Plugin Override" }],
supportsLocalAgentJwt: false,
};
registerServerAdapter(plugin);
// Plugin wins
const resolved = requireServerAdapter("claude_local");
expect(resolved).toBe(plugin);
expect(resolved.models).toEqual([
{ id: "plugin-model", label: "Plugin Override" },
]);
});
it("ships Hermes adapters as built-ins and still accepts external overrides", () => {
const builtInLocal = findServerAdapter("hermes_local");
const builtInGateway = findServerAdapter("hermes_gateway");
expect(builtInLocal).not.toBeNull();
expect(builtInLocal?.supportsLocalAgentJwt).toBe(true);
expect(builtInLocal?.supportsInstructionsBundle).toBe(true);
expect(builtInLocal?.requiresMaterializedRuntimeSkills).toBe(false);
expect(builtInLocal?.detectModel).toBeTypeOf("function");
expect(builtInLocal?.getConfigSchema).toBeTypeOf("function");
expect(builtInGateway).not.toBeNull();
expect(builtInGateway?.supportsLocalAgentJwt).toBe(false);
expect(builtInGateway?.supportsInstructionsBundle).toBe(false);
expect(builtInGateway?.requiresMaterializedRuntimeSkills).toBe(false);
expect(builtInGateway?.getConfigSchema).toBeTypeOf("function");
const hermesLocalExternalAdapter: ServerAdapterModule = {
type: "hermes_local",
execute: async () => ({ exitCode: 0, signal: null, timedOut: false }),
testEnvironment: async () => ({
adapterType: "hermes_local",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
supportsLocalAgentJwt: true,
supportsInstructionsBundle: true,
instructionsPathKey: "instructionsFilePath",
requiresMaterializedRuntimeSkills: false,
listSkills: async () => ({
adapterType: "hermes_local",
supported: true,
mode: "ephemeral",
desiredSkills: [],
entries: [],
warnings: [],
}),
getConfigSchema: () => ({ fields: [{ key: "provider", label: "Provider", type: "text" }] }),
detectModel: async () => ({
model: "hermes-model",
provider: "openrouter",
source: "test",
}),
};
const hermesGatewayExternalAdapter: ServerAdapterModule = {
type: "hermes_gateway",
execute: async () => ({ exitCode: 0, signal: null, timedOut: false }),
testEnvironment: async () => ({
adapterType: "hermes_gateway",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
supportsLocalAgentJwt: false,
supportsInstructionsBundle: false,
requiresMaterializedRuntimeSkills: false,
getConfigSchema: () => ({
fields: [{ key: "apiBaseUrl", label: "API URL", type: "text" }],
}),
};
registerServerAdapter(hermesLocalExternalAdapter);
expect(requireServerAdapter("hermes_local")).toBe(hermesLocalExternalAdapter);
expect(findActiveServerAdapter("hermes_local")?.supportsLocalAgentJwt).toBe(true);
unregisterServerAdapter("hermes_local");
expect(requireServerAdapter("hermes_local")).toBe(builtInLocal);
registerServerAdapter(hermesGatewayExternalAdapter);
expect(requireServerAdapter("hermes_gateway")).toBe(hermesGatewayExternalAdapter);
expect(findActiveServerAdapter("hermes_gateway")?.supportsLocalAgentJwt).toBe(false);
unregisterServerAdapter("hermes_gateway");
expect(requireServerAdapter("hermes_gateway")).toBe(builtInGateway);
});
it("exposes capability flags from registered adapters", () => {
const adapterWithCaps: ServerAdapterModule = {
type: "external_test",
execute: async () => ({ exitCode: 0, signal: null, timedOut: false }),
testEnvironment: async () => ({
adapterType: "external_test",
status: "pass" as const,
checks: [],
testedAt: new Date(0).toISOString(),
}),
supportsLocalAgentJwt: true,
supportsInstructionsBundle: true,
instructionsPathKey: "customPathKey",
requiresMaterializedRuntimeSkills: true,
};
registerServerAdapter(adapterWithCaps);
const resolved = findActiveServerAdapter("external_test");
expect(resolved).not.toBeNull();
expect(resolved!.supportsInstructionsBundle).toBe(true);
expect(resolved!.instructionsPathKey).toBe("customPathKey");
expect(resolved!.requiresMaterializedRuntimeSkills).toBe(true);
expect(resolved!.supportsLocalAgentJwt).toBe(true);
});
it("returns undefined for capability flags on adapters that do not set them", () => {
registerServerAdapter(externalAdapter);
const resolved = findActiveServerAdapter("external_test");
expect(resolved).not.toBeNull();
expect(resolved!.supportsInstructionsBundle).toBeUndefined();
expect(resolved!.instructionsPathKey).toBeUndefined();
expect(resolved!.requiresMaterializedRuntimeSkills).toBeUndefined();
});
it("built-in claude_local adapter declares capability flags", () => {
const adapter = findActiveServerAdapter("claude_local");
expect(adapter).not.toBeNull();
expect(adapter!.supportsInstructionsBundle).toBe(true);
expect(adapter!.instructionsPathKey).toBe("instructionsFilePath");
expect(adapter!.requiresMaterializedRuntimeSkills).toBe(false);
expect(adapter!.supportsLocalAgentJwt).toBe(true);
});
it("rejects an incomplete managed runner provider before probing Codex", async () => {
const adapter = requireServerAdapter("paperclip_runner");
expect(adapter.supportsInstructionsBundle).toBe(true);
expect(adapter.instructionsPathKey).toBe("instructionsFilePath");
const result = await adapter.testEnvironment({
companyId: "company-1",
adapterType: "paperclip_runner",
config: { provider: "claude_managed" },
});
expect(result).toMatchObject({
adapterType: "paperclip_runner",
status: "fail",
checks: [{
code: "paperclip_runner_claude_managed_profile_required",
level: "error",
}],
});
});
it.each(["pass", "fail"] as const)("uses the selected native Codex runtime for setup (%s)", async status => {
nativeSetup.authenticate.mockReset().mockResolvedValue({ adapterType: "paperclip_runner", status, testedAt: "", checks: [{ code: `codex_hello_probe_${status === "pass" ? "passed" : "auth_required"}`, level: status === "pass" ? "info" : "error", message: "Selected native account" }] });
const context = { companyId: "company-1", adapterType: "paperclip_runner", config: { provider: "codex", model: "gpt-5.6-sol", modelReasoningEffort: "high", env: { OPENAI_API_KEY: "selected-key" } } };
const result = await requireServerAdapter("paperclip_runner").testEnvironment(context);
expect(result.status).toBe(status);
expect(nativeSetup.authenticate).toHaveBeenCalledWith(context, "codex", "gpt-5.6-sol");
});
it("identifies only active external overrides for automatic runner selection", () => {
try {
expect(hasActiveAdapterOverride("codex_local")).toBe(false);
registerServerAdapter({ ...externalAdapter, type: "codex_local" });
expect(hasActiveAdapterOverride("codex_local")).toBe(true);
setOverridePaused("codex_local", true);
expect(hasActiveAdapterOverride("codex_local")).toBe(false);
setOverridePaused("codex_local", false);
expect(hasActiveAdapterOverride("codex_local")).toBe(true);
} finally { unregisterServerAdapter("codex_local"); }
});
it.each([
["claude_managed", {
managedProfileId: "managed-primary",
managedAgentsRetentionAcknowledged: true,
}, "claude_managed_profile_selected"],
["aws_agentcore", {
agentCoreProfileId: "agentcore-primary",
agentCoreRetentionAcknowledged: true,
}, "aws_agentcore_profile_selected"],
] as const)("accepts a complete %s profile selection", async (provider, config, code) => {
const result = await requireServerAdapter("paperclip_runner").testEnvironment({
companyId: "company-1",
adapterType: "paperclip_runner",
config: { provider, ...config },
});
expect(result).toMatchObject({
adapterType: "paperclip_runner",
status: "warn",
checks: expect.arrayContaining([expect.objectContaining({ code, level: "info" })]),
});
});
it.each([
["claude", "claude-sonnet-5"],
] as const)("does not claim runtime readiness from the remote ACPX %s platform alone", async (acpxAgent, model) => {
const result = await requireServerAdapter("paperclip_runner").testEnvironment({
companyId: "company-1",
adapterType: "paperclip_runner",
config: { provider: "acpx", acpxAgent, model },
executionTarget: {
kind: "remote",
transport: "sandbox",
remoteCwd: "/workspace",
providerKey: "test-provider",
runner: { execute: vi.fn().mockResolvedValue({ exitCode: 0, timedOut: false, stdout: "Linux\nx86_64\n" }) },
},
});
expect(result).toMatchObject({
adapterType: "paperclip_runner",
status: "warn",
checks: [{ code: "acpx_remote_runtime_unverified", level: "warn" }],
});
});
it.each([true, false])("checks actual local ACPX installation readiness (%s)", async (ready) => {
const probe = vi.mocked(probeAcpxClaudeInstallation);
if (ready) probe.mockResolvedValueOnce(undefined);
else probe.mockRejectedValueOnce(new Error("Runtime package integrity verification failed"));
const result = await requireServerAdapter("paperclip_runner").testEnvironment({
companyId: "company-1", adapterType: "paperclip_runner",
config: { provider: "acpx", acpxAgent: "claude", model: "custom-claude-model" },
});
expect(probe).toHaveBeenLastCalledWith("custom-claude-model");
expect(result).toMatchObject({
status: ready ? "pass" : "fail",
checks: [expect.objectContaining({ code: ready ? "acpx_runtime_ready" : "acpx_runtime_unavailable" })],
});
});
it.each([true, false])("probes the exact Pi installation without qualification opt-in (ready=%s)", async (ready) => {
const probe = vi.mocked(probeAcpxPiInstallation);
if (ready) probe.mockResolvedValueOnce(undefined);
else probe.mockRejectedValueOnce(new Error("Pi closure unavailable"));
const result = await requireServerAdapter("paperclip_runner").testEnvironment({
companyId: "company-1",
adapterType: "paperclip_runner",
config: {
provider: "acpx",
acpxAgent: "pi",
model: "openrouter/deepseek/deepseek-v4-flash-0731",
},
});
expect(result).toMatchObject({
status: ready ? "pass" : "fail",
checks: [{ code: ready ? "acpx_runtime_ready" : "acpx_runtime_unavailable" }],
});
expect(probe).toHaveBeenLastCalledWith("openrouter/deepseek/deepseek-v4-flash-0731");
});
it("requires a saved Copilot token rather than ambient authentication",async()=>{
const prior=process.env.COPILOT_GITHUB_TOKEN;process.env.COPILOT_GITHUB_TOKEN="ambient-not-authority";
const probe=vi.mocked(probeCopilotExecutionTarget);probe.mockClear();
try{
const result=await requireServerAdapter("paperclip_runner").testEnvironment({companyId:"company-1",adapterType:"paperclip_runner",config:{provider:"acpx",acpxAgent:"copilot",model:"gpt-5.6-luna"}});
expect(result).toMatchObject({status:"fail",checks:[{code:"COPILOT_AUTH_REQUIRED"}]});expect(probe).not.toHaveBeenCalled();
}finally{if(prior===undefined)delete process.env.COPILOT_GITHUB_TOKEN;else process.env.COPILOT_GITHUB_TOKEN=prior;}
});
it.each([undefined,{kind:"remote",remoteCwd:"/workspace"}])("verifies the selected Copilot runtime and model without a prompt",async(executionTarget)=>{
const result=await requireServerAdapter("paperclip_runner").testEnvironment({companyId:"company-1",adapterType:"paperclip_runner",config:{provider:"acpx",acpxAgent:"copilot",model:"gpt-5.6-luna",env:{COPILOT_GITHUB_TOKEN:"fixture-token"}},executionTarget} as any);
expect(probeCopilotExecutionTarget).toHaveBeenLastCalledWith("fixture-token",executionTarget,"gpt-5.6-luna");
expect(result).toMatchObject({status:"pass",checks:[{code:"copilot_metadata_verified"}]});
});
it.each(["COPILOT_AUTH_REQUIRED","COPILOT_ENTITLEMENT_DENIED","COPILOT_MODEL_UNAVAILABLE","COPILOT_INSTALLATION_INVALID","COPILOT_REQUEST_FAILED"])("reports distinct Copilot failure %s",async code=>{
vi.mocked(probeCopilotExecutionTarget).mockRejectedValueOnce(new HttpError(422,"Fixture metadata failure",{code}));
const result=await requireServerAdapter("paperclip_runner").testEnvironment({companyId:"company-1",adapterType:"paperclip_runner",config:{provider:"acpx",acpxAgent:"copilot",model:"gpt-5.6-luna",env:{COPILOT_GITHUB_TOKEN:"fixture-token"}}});
expect(result).toMatchObject({status:"fail",checks:[{code}]});
});
it("sanitizes unexpected Copilot metadata failures",async()=>{
vi.mocked(probeCopilotExecutionTarget).mockRejectedValueOnce(new Error("fixture private implementation detail"));
const result=await requireServerAdapter("paperclip_runner").testEnvironment({companyId:"company-1",adapterType:"paperclip_runner",config:{provider:"acpx",acpxAgent:"copilot",model:"gpt-5.6-luna",env:{COPILOT_GITHUB_TOKEN:"fixture-token"}}});
expect(result).toMatchObject({status:"fail",checks:[{code:"COPILOT_REQUEST_FAILED",message:"Copilot metadata verification failed."}]});
expect(JSON.stringify(result)).not.toContain("private implementation detail");
});
it("wraps built-in npm runtime installs with the sandbox-aware install helper", () => {
const expectedClaudeInstall = `if ! command -v 'claude' >/dev/null 2>&1; then ${buildSandboxNpmInstallCommand("@anthropic-ai/claude-code")}; fi`;
const expectedCodexInstall = `if ! command -v 'codex' >/dev/null 2>&1; then ${buildSandboxNpmInstallCommand("@openai/codex")}; fi`;
const expectedGeminiInstall = `if ! command -v 'gemini' >/dev/null 2>&1; then ${buildSandboxNpmInstallCommand("@google/gemini-cli")}; fi`;
const expectedOpenCodeInstall = `if ! command -v 'opencode' >/dev/null 2>&1; then ${buildSandboxNpmInstallCommand("opencode-ai")}; fi`;
const expectedRunnerCodexInstall = `if ! command -v 'codex' >/dev/null 2>&1; then ${buildSandboxNpmInstallCommand("@openai/codex@0.160.0")}; fi`;
const expectedRunnerOpenCodeInstall = `if ! command -v 'opencode' >/dev/null 2>&1; then ${buildSandboxNpmInstallCommand("opencode-ai@1.18.34")}; fi`;
expect(findActiveServerAdapter("claude_local")?.getRuntimeCommandSpec?.({})).toEqual({
command: "claude",
detectCommand: "claude",
installCommand: expectedClaudeInstall,
});
expect(findActiveServerAdapter("codex_local")?.getRuntimeCommandSpec?.({})).toEqual({
command: "codex",
detectCommand: "codex",
installCommand: expectedCodexInstall,
});
expect(findActiveServerAdapter("gemini_local")?.getRuntimeCommandSpec?.({})).toEqual({
command: "gemini",
detectCommand: "gemini",
installCommand: expectedGeminiInstall,
});
expect(findActiveServerAdapter("opencode_local")?.getRuntimeCommandSpec?.({})).toEqual({
command: "opencode",
detectCommand: "opencode",
installCommand: expectedOpenCodeInstall,
});
expect(findActiveServerAdapter("paperclip_runner")?.getRuntimeCommandSpec?.({ provider: "codex" })).toEqual({
command: "codex",
detectCommand: "codex",
installCommand: expectedRunnerCodexInstall,
});
expect(findActiveServerAdapter("paperclip_runner")?.getRuntimeCommandSpec?.({ provider: "opencode" })).toEqual({
command: "opencode",
detectCommand: "opencode",
installCommand: expectedRunnerOpenCodeInstall,
});
expect(findActiveServerAdapter("paperclip_runner")?.getRuntimeCommandSpec?.({ provider: "acpx" })).toEqual({
command: "paperclip-runnerd",
detectCommand: null,
installCommand: null,
});
});
it("switches active adapter behavior back to the builtin when an override is paused", async () => {
const builtIn = findServerAdapter("claude_local");
expect(builtIn).not.toBeNull();
const detectModel = vi.fn(async () => ({
model: "plugin-model",
provider: "plugin-provider",
source: "plugin-source",
}));
const plugin: ServerAdapterModule = {
type: "claude_local",
execute: async () => ({
exitCode: 0,
signal: null,
timedOut: false,
}),
testEnvironment: async () => ({
adapterType: "claude_local",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
models: [{ id: "plugin-model", label: "Plugin Override" }],
detectModel,
supportsLocalAgentJwt: false,
};
registerServerAdapter(plugin);
expect(findActiveServerAdapter("claude_local")).toBe(plugin);
expect(await listAdapterModels("claude_local")).toEqual([
{ id: "plugin-model", label: "Plugin Override" },
]);
expect(await detectAdapterModel("claude_local")).toMatchObject({
model: "plugin-model",
provider: "plugin-provider",
});
expect(setOverridePaused("claude_local", true)).toBe(true);
expect(findActiveServerAdapter("claude_local")).not.toBe(plugin);
expect(await listAdapterModels("claude_local")).toEqual(builtIn?.models ?? []);
expect(await detectAdapterModel("claude_local")).toBeNull();
expect(detectModel).toHaveBeenCalledTimes(1);
});
});
describe("resolveExternalAdapterRegistration", () => {
it("preserves module-provided sessionManagement", () => {
const sessionManagement = {
supportsSessionResume: true,
nativeContextManagement: "unknown" as const,
defaultSessionCompaction: {
enabled: true,
maxSessionRuns: 200,
maxRawInputTokens: 2_000_000,
maxSessionAgeHours: 72,
},
};
const adapter: ServerAdapterModule = {
type: "external_session_test",
execute: async () => ({ exitCode: 0, signal: null, timedOut: false }),
testEnvironment: async () => ({
adapterType: "external_session_test",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
sessionManagement,
};
const resolved = resolveExternalAdapterRegistration(adapter);
expect(resolved.sessionManagement).toBe(sessionManagement);
});
it("falls back to the hardcoded registry when the module omits sessionManagement", () => {
// An external that overrides a built-in type should inherit the built-in's
// sessionManagement when it does not provide its own.
const adapter: ServerAdapterModule = {
type: "claude_local",
execute: async () => ({ exitCode: 0, signal: null, timedOut: false }),
testEnvironment: async () => ({
adapterType: "claude_local",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
};
const resolved = resolveExternalAdapterRegistration(adapter);
expect(resolved.sessionManagement).toBeDefined();
expect(resolved.sessionManagement?.supportsSessionResume).toBe(true);
expect(resolved.sessionManagement?.nativeContextManagement).toBe("confirmed");
});
it("leaves sessionManagement undefined when neither module nor registry provides one", () => {
const adapter: ServerAdapterModule = {
type: "external_unknown_test",
execute: async () => ({ exitCode: 0, signal: null, timedOut: false }),
testEnvironment: async () => ({
adapterType: "external_unknown_test",
status: "pass",
checks: [],
testedAt: new Date(0).toISOString(),
}),
};
const resolved = resolveExternalAdapterRegistration(adapter);
expect(resolved.sessionManagement).toBeUndefined();
});
});