import { Show, createEffect, createSignal } from "solid-js";
import { ProjectsService } from "@primora/api-client";
import { demoService } from "../lib/demo-mode";
import { buildAgentPrompt } from "../lib/agent-prompt";
import { errorMessage } from "../lib/api";
import { Modal, ModalFooter } from "./Modal";
import { IconCheck, IconCopy, IconKey, IconRefresh } from "./Icons";
export interface AgentSetupProject {
id: string;
name: string;
slug: string;
}
interface AgentSetupModalProps {
open: boolean;
onClose: () => void;
project?: AgentSetupProject;
canManage: boolean;
demoMode: boolean;
/** called after a key is minted so the app can refetch keys/audit/overview */
onKeyCreated?: () => void;
}
export function AgentSetupModal(props: AgentSetupModalProps) {
const [prompt, setPrompt] = createSignal("");
const [keyPrefix, setKeyPrefix] = createSignal("");
const [busy, setBusy] = createSignal(false);
const [error, setError] = createSignal("");
const [copied, setCopied] = createSignal(false);
const generate = async () => {
const project = props.project;
if (!project || busy()) return;
setBusy(true);
setError("");
setCopied(false);
try {
const stamp = new Date().toISOString().slice(0, 16).replace(/[:T]/g, "");
const result = props.demoMode
? await demoService.createApiKey({ requestBody: { name: `agent-setup-${stamp}` } })
: await ProjectsService.createApiKey({
projectId: project.id,
requestBody: { name: `agent-setup-${stamp}`, scopes: ["write"] },
});
setKeyPrefix(result.prefix);
setPrompt(
buildAgentPrompt({
baseUrl: window.location.origin,
projectId: project.id,
projectName: project.name,
projectSlug: project.slug,
apiKey: result.secret,
}),
);
props.onKeyCreated?.();
} catch (e) {
setError(errorMessage(e, "Could not create an API key"));
} finally {
setBusy(false);
}
};
// Mint a fresh write-scoped key each time the modal opens — secrets are
// shown once, so a cached prompt would carry a dead credential. The error
// guard prevents a retry loop when minting fails; the user retries manually.
createEffect(() => {
if (props.open && props.project && props.canManage && !prompt() && !busy() && !error()) {
void generate();
}
if (!props.open) {
setPrompt("");
setKeyPrefix("");
setError("");
setCopied(false);
}
});
const copyPrompt = async () => {
try {
await navigator.clipboard.writeText(prompt());
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
/* clipboard unavailable — the text is selectable instead */
}
};
return (
{prompt()}