0dfb93e898
Tests: - adapter-registry: verify capability flags are exposed, undefined when unset, and correctly declared on built-in claude_local adapter - adapter-routes: verify GET /api/adapters includes capabilities object, correct flags for codex_local/process/cursor, and derived supportsSkills Documentation: - docs/adapters/creating-an-adapter.md: new "Capability Flags" section documenting all flags, their defaults, and usage example for external adapter plugins Co-Authored-By: Paperclip <noreply@paperclip.ing>
189 lines
6.1 KiB
TypeScript
189 lines
6.1 KiB
TypeScript
import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
|
|
import type { ServerAdapterModule } from "../adapters/index.js";
|
|
import {
|
|
detectAdapterModel,
|
|
findActiveServerAdapter,
|
|
findServerAdapter,
|
|
listAdapterModels,
|
|
registerServerAdapter,
|
|
requireServerAdapter,
|
|
unregisterServerAdapter,
|
|
} from "../adapters/index.js";
|
|
import { setOverridePaused } from "../adapters/registry.js";
|
|
|
|
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("claude_local");
|
|
setOverridePaused("claude_local", false);
|
|
});
|
|
|
|
afterEach(() => {
|
|
unregisterServerAdapter("external_test");
|
|
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("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("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);
|
|
});
|
|
});
|