Improve imported agent adapter selection
This commit is contained in:
@@ -471,4 +471,71 @@ describe("company portability", () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("applies adapter overrides while keeping imported AGENTS content implicit", async () => {
|
||||
const portability = companyPortabilityService({} as any);
|
||||
|
||||
companySvc.create.mockResolvedValue({
|
||||
id: "company-imported",
|
||||
name: "Imported Paperclip",
|
||||
});
|
||||
accessSvc.ensureMembership.mockResolvedValue(undefined);
|
||||
agentSvc.create.mockResolvedValue({
|
||||
id: "agent-created",
|
||||
name: "ClaudeCoder",
|
||||
});
|
||||
|
||||
const exported = await portability.exportBundle("company-1", {
|
||||
include: {
|
||||
company: true,
|
||||
agents: true,
|
||||
projects: false,
|
||||
issues: false,
|
||||
},
|
||||
});
|
||||
|
||||
agentSvc.list.mockResolvedValue([]);
|
||||
|
||||
await portability.importBundle({
|
||||
source: {
|
||||
type: "inline",
|
||||
rootPath: exported.rootPath,
|
||||
files: exported.files,
|
||||
},
|
||||
include: {
|
||||
company: true,
|
||||
agents: true,
|
||||
projects: false,
|
||||
issues: false,
|
||||
},
|
||||
target: {
|
||||
mode: "new_company",
|
||||
newCompanyName: "Imported Paperclip",
|
||||
},
|
||||
agents: "all",
|
||||
collisionStrategy: "rename",
|
||||
adapterOverrides: {
|
||||
claudecoder: {
|
||||
adapterType: "codex_local",
|
||||
adapterConfig: {
|
||||
dangerouslyBypassApprovalsAndSandbox: true,
|
||||
instructionsFilePath: "/tmp/should-not-survive.md",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, "user-1");
|
||||
|
||||
expect(agentSvc.create).toHaveBeenCalledWith("company-imported", expect.objectContaining({
|
||||
adapterType: "codex_local",
|
||||
adapterConfig: expect.objectContaining({
|
||||
promptTemplate: "You are ClaudeCoder.",
|
||||
dangerouslyBypassApprovalsAndSandbox: true,
|
||||
}),
|
||||
}));
|
||||
expect(agentSvc.create).toHaveBeenCalledWith("company-imported", expect.objectContaining({
|
||||
adapterConfig: expect.not.objectContaining({
|
||||
instructionsFilePath: expect.anything(),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2274,7 +2274,7 @@ export function companyPortabilityService(db: Db) {
|
||||
baseAdapterConfig,
|
||||
desiredSkills,
|
||||
);
|
||||
delete baseAdapterConfig.instructionsFilePath;
|
||||
delete adapterConfigWithSkills.instructionsFilePath;
|
||||
const patch = {
|
||||
name: planAgent.plannedName,
|
||||
role: manifestAgent.role,
|
||||
|
||||
@@ -17,7 +17,9 @@ export function GeminiLocalConfigFields({
|
||||
config,
|
||||
eff,
|
||||
mark,
|
||||
hideInstructionsFile,
|
||||
}: AdapterConfigFieldsProps) {
|
||||
if (hideInstructionsFile) return null;
|
||||
return (
|
||||
<>
|
||||
<Field label="Agent instructions file" hint={instructionsFileHint}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export { getUIAdapter } from "./registry";
|
||||
export { getUIAdapter, listUIAdapters } from "./registry";
|
||||
export { buildTranscript } from "./transcript";
|
||||
export type {
|
||||
TranscriptEntry,
|
||||
|
||||
@@ -17,7 +17,9 @@ export function PiLocalConfigFields({
|
||||
config,
|
||||
eff,
|
||||
mark,
|
||||
hideInstructionsFile,
|
||||
}: AdapterConfigFieldsProps) {
|
||||
if (hideInstructionsFile) return null;
|
||||
return (
|
||||
<Field label="Agent instructions file" hint={instructionsFileHint}>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -9,20 +9,26 @@ import { openClawGatewayUIAdapter } from "./openclaw-gateway";
|
||||
import { processUIAdapter } from "./process";
|
||||
import { httpUIAdapter } from "./http";
|
||||
|
||||
const uiAdapters: UIAdapterModule[] = [
|
||||
claudeLocalUIAdapter,
|
||||
codexLocalUIAdapter,
|
||||
geminiLocalUIAdapter,
|
||||
openCodeLocalUIAdapter,
|
||||
piLocalUIAdapter,
|
||||
cursorLocalUIAdapter,
|
||||
openClawGatewayUIAdapter,
|
||||
processUIAdapter,
|
||||
httpUIAdapter,
|
||||
];
|
||||
|
||||
const adaptersByType = new Map<string, UIAdapterModule>(
|
||||
[
|
||||
claudeLocalUIAdapter,
|
||||
codexLocalUIAdapter,
|
||||
geminiLocalUIAdapter,
|
||||
openCodeLocalUIAdapter,
|
||||
piLocalUIAdapter,
|
||||
cursorLocalUIAdapter,
|
||||
openClawGatewayUIAdapter,
|
||||
processUIAdapter,
|
||||
httpUIAdapter,
|
||||
].map((a) => [a.type, a]),
|
||||
uiAdapters.map((a) => [a.type, a]),
|
||||
);
|
||||
|
||||
export function getUIAdapter(type: string): UIAdapterModule {
|
||||
return adaptersByType.get(type) ?? processUIAdapter;
|
||||
}
|
||||
|
||||
export function listUIAdapters(): UIAdapterModule[] {
|
||||
return [...uiAdapters];
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { Field, adapterLabels } from "../components/agent-config-primitives";
|
||||
import { defaultCreateValues } from "../components/agent-config-defaults";
|
||||
import { getUIAdapter } from "../adapters";
|
||||
import { getUIAdapter, listUIAdapters } from "../adapters";
|
||||
import { ClaudeLocalAdvancedFields } from "../adapters/claude-local/config-fields";
|
||||
import type { CreateConfigValues } from "@paperclipai/adapter-utils";
|
||||
import {
|
||||
@@ -443,12 +443,10 @@ function ConflictResolutionList({
|
||||
|
||||
// ── Adapter type options for import ───────────────────────────────────
|
||||
|
||||
const IMPORT_ADAPTER_OPTIONS: { value: string; label: string }[] = [
|
||||
{ value: "claude_local", label: adapterLabels.claude_local ?? "Claude (local)" },
|
||||
{ value: "codex_local", label: adapterLabels.codex_local ?? "Codex (local)" },
|
||||
{ value: "opencode_local", label: adapterLabels.opencode_local ?? "OpenCode (local)" },
|
||||
{ value: "cursor", label: adapterLabels.cursor ?? "Cursor (local)" },
|
||||
];
|
||||
const IMPORT_ADAPTER_OPTIONS: { value: string; label: string }[] = listUIAdapters().map((adapter) => ({
|
||||
value: adapter.type,
|
||||
label: adapterLabels[adapter.type] ?? adapter.label,
|
||||
}));
|
||||
|
||||
// ── Adapter picker for imported agents ───────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user