Files
paperclip/server/src/adapters/registry.ts
Dotta 3b4db7a3bc Merge remote-tracking branch 'public-gh/master'
* public-gh/master:
  Address PR feedback: keep testEnvironment non-destructive, warn on swallowed errors
  Apply suggestion from @greptile-apps[bot]
  Fix opencode-local adapter: parser, UI, CLI, and environment tests
  Rename Invoke button to Run Heartbeat for clarity
  fixing overhanging recommended text in onboarding
  Add Contributing guide
  feat(pi-local): fix bugs, add RPC mode, improve cost tracking and output handling
  fix(sidebar-badges): include approvals in inbox badge count
  feat: add Pi adapter support to constants and onboarding UI
  Adding support for pi-local
  ci: clarify fail-fast lockfile refresh behavior
  ci: remove unnecessary full-history checkout
  ci: fix pnpm lockfile policy checks
  ci: split workflows and move pnpm lockfile ownership to GitHub Actions
  Add License
  fix: use root option in sendFile to avoid dotfile 500 on SPA refresh

# Conflicts:
#	cli/src/adapters/registry.ts
#	pnpm-lock.yaml
#	server/src/adapters/registry.ts
#	ui/package.json
#	ui/src/adapters/registry.ts
2026-03-07 15:18:02 -06:00

173 lines
5.5 KiB
TypeScript

import type { ServerAdapterModule } from "./types.js";
import {
execute as claudeExecute,
testEnvironment as claudeTestEnvironment,
sessionCodec as claudeSessionCodec,
} from "@paperclipai/adapter-claude-local/server";
import { agentConfigurationDoc as claudeAgentConfigurationDoc, models as claudeModels } from "@paperclipai/adapter-claude-local";
import {
execute as codexExecute,
testEnvironment as codexTestEnvironment,
sessionCodec as codexSessionCodec,
} from "@paperclipai/adapter-codex-local/server";
import { agentConfigurationDoc as codexAgentConfigurationDoc, models as codexModels } from "@paperclipai/adapter-codex-local";
import {
execute as cursorExecute,
testEnvironment as cursorTestEnvironment,
sessionCodec as cursorSessionCodec,
} from "@paperclipai/adapter-cursor-local/server";
import { agentConfigurationDoc as cursorAgentConfigurationDoc, models as cursorModels } from "@paperclipai/adapter-cursor-local";
import {
execute as openCodeExecute,
testEnvironment as openCodeTestEnvironment,
sessionCodec as openCodeSessionCodec,
listOpenCodeModels,
} from "@paperclipai/adapter-opencode-local/server";
import {
agentConfigurationDoc as openCodeAgentConfigurationDoc,
} from "@paperclipai/adapter-opencode-local";
import {
execute as openclawExecute,
testEnvironment as openclawTestEnvironment,
onHireApproved as openclawOnHireApproved,
} from "@paperclipai/adapter-openclaw/server";
import {
agentConfigurationDoc as openclawAgentConfigurationDoc,
models as openclawModels,
} from "@paperclipai/adapter-openclaw";
import {
execute as openclawGatewayExecute,
testEnvironment as openclawGatewayTestEnvironment,
} from "@paperclipai/adapter-openclaw-gateway/server";
import {
agentConfigurationDoc as openclawGatewayAgentConfigurationDoc,
models as openclawGatewayModels,
} from "@paperclipai/adapter-openclaw-gateway";
import { listCodexModels } from "./codex-models.js";
import { listCursorModels } from "./cursor-models.js";
import {
execute as piExecute,
testEnvironment as piTestEnvironment,
sessionCodec as piSessionCodec,
listPiModels,
} from "@paperclipai/adapter-pi-local/server";
import {
agentConfigurationDoc as piAgentConfigurationDoc,
} from "@paperclipai/adapter-pi-local";
import { processAdapter } from "./process/index.js";
import { httpAdapter } from "./http/index.js";
const claudeLocalAdapter: ServerAdapterModule = {
type: "claude_local",
execute: claudeExecute,
testEnvironment: claudeTestEnvironment,
sessionCodec: claudeSessionCodec,
models: claudeModels,
supportsLocalAgentJwt: true,
agentConfigurationDoc: claudeAgentConfigurationDoc,
};
const codexLocalAdapter: ServerAdapterModule = {
type: "codex_local",
execute: codexExecute,
testEnvironment: codexTestEnvironment,
sessionCodec: codexSessionCodec,
models: codexModels,
listModels: listCodexModels,
supportsLocalAgentJwt: true,
agentConfigurationDoc: codexAgentConfigurationDoc,
};
const cursorLocalAdapter: ServerAdapterModule = {
type: "cursor",
execute: cursorExecute,
testEnvironment: cursorTestEnvironment,
sessionCodec: cursorSessionCodec,
models: cursorModels,
listModels: listCursorModels,
supportsLocalAgentJwt: true,
agentConfigurationDoc: cursorAgentConfigurationDoc,
};
const openclawAdapter: ServerAdapterModule = {
type: "openclaw",
execute: openclawExecute,
testEnvironment: openclawTestEnvironment,
onHireApproved: openclawOnHireApproved,
models: openclawModels,
supportsLocalAgentJwt: false,
agentConfigurationDoc: openclawAgentConfigurationDoc,
};
const openclawGatewayAdapter: ServerAdapterModule = {
type: "openclaw_gateway",
execute: openclawGatewayExecute,
testEnvironment: openclawGatewayTestEnvironment,
models: openclawGatewayModels,
supportsLocalAgentJwt: false,
agentConfigurationDoc: openclawGatewayAgentConfigurationDoc,
};
const openCodeLocalAdapter: ServerAdapterModule = {
type: "opencode_local",
execute: openCodeExecute,
testEnvironment: openCodeTestEnvironment,
sessionCodec: openCodeSessionCodec,
models: [],
listModels: listOpenCodeModels,
supportsLocalAgentJwt: true,
agentConfigurationDoc: openCodeAgentConfigurationDoc,
};
const piLocalAdapter: ServerAdapterModule = {
type: "pi_local",
execute: piExecute,
testEnvironment: piTestEnvironment,
sessionCodec: piSessionCodec,
models: [],
listModels: listPiModels,
supportsLocalAgentJwt: true,
agentConfigurationDoc: piAgentConfigurationDoc,
};
const adaptersByType = new Map<string, ServerAdapterModule>(
[
claudeLocalAdapter,
codexLocalAdapter,
openCodeLocalAdapter,
piLocalAdapter,
cursorLocalAdapter,
openclawAdapter,
openclawGatewayAdapter,
processAdapter,
httpAdapter,
].map((a) => [a.type, a]),
);
export function getServerAdapter(type: string): ServerAdapterModule {
const adapter = adaptersByType.get(type);
if (!adapter) {
// Fall back to process adapter for unknown types
return processAdapter;
}
return adapter;
}
export async function listAdapterModels(type: string): Promise<{ id: string; label: string }[]> {
const adapter = adaptersByType.get(type);
if (!adapter) return [];
if (adapter.listModels) {
const discovered = await adapter.listModels();
if (discovered.length > 0) return discovered;
}
return adapter.models ?? [];
}
export function listServerAdapters(): ServerAdapterModule[] {
return Array.from(adaptersByType.values());
}
export function findServerAdapter(type: string): ServerAdapterModule | null {
return adaptersByType.get(type) ?? null;
}