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 ( Generating credentials requires the project admin role. Ask a project admin to open this dialog and copy the prompt for you.

} > Creating a write-scoped API key… } >
Fresh key {keyPrefix()}… minted — shown only inside this prompt.{" "} It grants write access to this project; revoke it under Settings → API keys if the prompt leaks or the agent finishes.
            {prompt()}
          
); }