@animaapp/cli 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/auth/store.ts","../src/auth/jwt.ts","../src/api/errors.ts","../src/auth/agentSession.ts","../src/output/log.ts","../src/auth/refresh.ts","../src/config/store.ts","../src/auth/token.ts","../src/api/mcp.ts","../src/version.ts","../src/output/formatter.ts","../src/output/progress.ts","../src/output/pretty.ts","../src/utils/figma.ts","../src/utils/projectSource.ts","../src/utils/playgroundUrl.ts","../src/commands/list.ts","../src/commands/publish.ts","../src/commands/codegen.ts","../src/utils/files.ts","../src/commands/getGitToken.ts","../src/utils/gitToken.ts","../src/commands/mcpConfig.ts","../src/commands/login.ts","../src/auth/device.ts","../src/auth/invite.ts","../src/commands/auth.ts","../src/commands/logout.ts","../src/commands/unpublish.ts","../src/commands/update.ts","../src/commands/config.ts","../src/commands/duplicate.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createCommand } from \"./commands/create.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { publishCommand } from \"./commands/publish.js\";\nimport { codegenCommand } from \"./commands/codegen.js\";\nimport { getGitTokenCommand } from \"./commands/getGitToken.js\";\nimport { mcpConfigCommand } from \"./commands/mcpConfig.js\";\nimport { authCommand } from \"./commands/auth.js\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { logoutCommand } from \"./commands/logout.js\";\nimport { unpublishCommand } from \"./commands/unpublish.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { configCommand } from \"./commands/config.js\";\nimport { duplicateCommand } from \"./commands/duplicate.js\";\nimport { CliError } from \"./api/errors.js\";\n\n// Version comes from package.json so `--version` always matches the published\n// build (shared with the MCP clientInfo).\nimport { version } from \"./version.js\";\n\nconst program = new Command()\n .name(\"anima\")\n .description(\n `AgentGrid CLI — host, edit, and publish your work on AgentGrid. Every artifact is a\nreal git repository; each command runs an AgentGrid tool for you.\n\nTHE MAIN FLOW (build something and put it on AgentGrid):\n 1. npx @animaapp/cli login # once; a human approves\n 2. npx @animaapp/cli create -t import --from ./my-project # your code → a live app\n (or: create -t empty --framework html — an empty repo you push to)\n 3. The response includes a rw gitRemoteUrl — git clone, edit, commit, push:\n every push updates the live artifact.\n 4. Share the playgroundUrl with your human. That IS sharing — the artifact\n is visible at its URL. Do NOT run publish unless the human explicitly\n asked for a public site; offer it as a follow-up question instead.\n\nAUTHENTICATION:\n npx @animaapp/cli login # device flow — a human approves on any device\n npx @animaapp/cli login --invite <url> # redeem a pre-approved invite link (no approval step)\n Credentials live in ~/.config/anima/; logout removes everything.\n\nTIMING (important for AI agents):\n create -t empty|import → seconds\n create -t p2c|l2c|f2c → 3-7 minutes AI generation (keep the default 600000ms timeout)\n publish/unpublish → 1-3 minutes\n duplicate / get-git-token / update → seconds\n\nCOMMANDS:\n login Connect (device flow, or --invite to redeem an invite link)\n logout Full local reset — clears credentials and CLI config\n list List your team's artifacts (most-recently-updated first) to resume work\n create Make an artifact: import your code, empty repo, or AI-generated (p2c/l2c/f2c)\n duplicate Copy an artifact into a new, independent artifact\n get-git-token Fresh git access to an existing artifact (or after token expiry)\n update Rename an artifact or set visibility public/private (metadata only)\n publish Deploy to a public live URL — ONLY when the human asked for it\n unpublish Take a published artifact offline (inverse of publish)\n mcp-config Print an MCP server config from stored credentials (no new login)\n codegen Convert Figma design to local code files (no artifact)\n config Store CLI preferences (e.g. a default API URL)\n auth Inspect or manage credentials (status / figma token)\n\nEXAMPLES (headless flow):\n npx @animaapp/cli login --invite https://api.agentgrid.io/invite/<code>.md\n npx @animaapp/cli create -t import --from ./my-project\n npx @animaapp/cli create -t empty --framework react --name \"My app\"\n npx @animaapp/cli duplicate <artifactUrl> --name \"My copy\"\n npx @animaapp/cli get-git-token <sessionId>\n npx @animaapp/cli update <sessionId> --privacy public\n npx @animaapp/cli publish <sessionId> # only on explicit request\n npx @animaapp/cli unpublish <sessionId>\n\nOUTPUT: JSON to stdout when piped (for AI tools), pretty text in terminals.\n Progress is streamed to stderr via --verbose when in JSON mode.`\n )\n .version(version, \"-v, --version\");\n\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\nprogram.addCommand(listCommand);\nprogram.addCommand(createCommand);\nprogram.addCommand(duplicateCommand);\nprogram.addCommand(publishCommand);\nprogram.addCommand(unpublishCommand);\nprogram.addCommand(updateCommand);\nprogram.addCommand(codegenCommand);\nprogram.addCommand(getGitTokenCommand);\nprogram.addCommand(mcpConfigCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(authCommand);\n\nprogram.parseAsync(process.argv).catch((err) => {\n if (err instanceof CliError) {\n if (process.stdout.isTTY) {\n console.error(err.message);\n } else {\n process.stdout.write(\n JSON.stringify({\n success: false,\n error: { code: err.code, message: err.message },\n }) + \"\\n\"\n );\n }\n process.exit(err.exitCode);\n }\n\n console.error(err);\n process.exit(1);\n});\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSessionResult } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { collectProjectSource } from \"../utils/projectSource.js\";\nimport { PLAYGROUND_BASE } from \"../utils/playgroundUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { CreateType } from \"../api/types.js\";\n\n\ntype CreateResult = {\n success: boolean;\n sessionId?: string;\n playgroundUrl?: string;\n // Minted with the artifact, same shape as artifact-get_git_token.\n gitRemoteUrl?: string;\n access?: \"ro\" | \"rw\";\n expiresAt?: string;\n // Own-code only\n framework?: \"html\" | \"react\";\n artifactType?: \"app\" | \"markdown\" | \"asset\";\n fileCount?: number;\n skippedFiles?: string[];\n notes?: string;\n nextSteps?: string;\n error?: string;\n reason?: string;\n};\n\ntype ZipUploadGrant = {\n success: boolean;\n zipUploadId?: string;\n uploadUrl?: string;\n uploadUrlExpiresAt?: string;\n nextSteps?: string | string[];\n error?: string;\n reason?: string;\n};\n\nexport const createCommand = new Command(\"create\")\n .description(\n \"Create an artifact from your own code: empty for code you'll push (instant) or import your existing code (instant). Also supports AI generation: p2c/l2c/f2c (3-7 min).\"\n )\n .requiredOption(\n \"-t, --type <type>\",\n \"empty (empty repo you push to), import (create FROM your code — use --from), or AI-generated: p2c, l2c, f2c\"\n )\n .option(\"-p, --prompt <prompt>\", \"Text prompt (p2c)\")\n .option(\"-u, --url <url>\", \"Website URL (l2c)\")\n .option(\"--file-key <key>\", \"Figma file key or URL (f2c)\")\n .option(\"--nodes <nodes>\", \"Figma node IDs, comma-separated (f2c)\")\n .option(\"--figma-token <token>\", \"Figma personal access token (f2c)\")\n .option(\n \"--framework <fw>\",\n \"html | react — the only supported frameworks. REQUIRED for empty (declare react if you will push React code); detected from package.json for import\"\n )\n .option(\"--styling <style>\", \"tailwind | css | plain_css | css_modules | inline_styles\", \"tailwind\")\n .option(\"--language <lang>\", \"typescript | javascript\")\n .option(\"--ui-library <lib>\", \"mui | antd | shadcn | clean_react\")\n .option(\"--guidelines <text>\", \"Additional constraints (p2c only)\")\n .option(\n \"--artifact-type <kind>\",\n \"app | markdown \\u2014 what the artifact IS. app (default) needs an index.html; markdown needs .md files\"\n )\n .option(\"--name <name>\", \"Project name (empty/import only)\")\n .option(\"--from <path>\", \"Folder or .zip with your project (import only) — becomes the first commit\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const type = opts.type as CreateType;\n validateCreateOptions(type, opts);\n\n const auth = await resolveAuth(opts.apiUrl);\n const figmaToken = type === \"f2c\" ? resolveFigmaToken(opts, auth.figmaToken) : undefined;\n const args = buildCreateArgs(type, opts);\n const mcpConfig = { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId, figmaToken };\n\n // Import: attach the local project. Small text-only projects go inline;\n // anything with binaries or over the inline caps is zipped and uploaded\n // via a presigned URL first (artifact-get_zip_upload_url).\n if (type === \"import\") {\n progress.start(\"Collecting project files...\");\n const source = collectProjectSource(opts.from);\n if (source.kind === \"files\") {\n args.files = source.files;\n } else {\n progress.update(`Uploading project zip (${source.reason})...`);\n const grant = await withMcp(mcpConfig, (client) =>\n client.callTool<ZipUploadGrant>(\"artifact-get_zip_upload_url\", {})\n );\n if (!grant.success || !grant.uploadUrl || !grant.zipUploadId) {\n const message = grant.reason || grant.error || \"Could not get a zip upload URL\";\n throw apiError(grant.nextSteps ? `${message}\\n${grant.nextSteps}` : message, grant);\n }\n const putResponse = await fetch(grant.uploadUrl, {\n method: \"PUT\",\n body: new Uint8Array(source.buffer),\n });\n if (!putResponse.ok) {\n throw apiError(`Zip upload failed: HTTP ${putResponse.status}`, { status: putResponse.status });\n }\n args.zipUploadId = grant.zipUploadId;\n }\n }\n\n progress.start(\n type === \"empty\"\n ? \"Creating empty artifact...\"\n : type === \"import\"\n ? \"Importing your project...\"\n : `Creating ${type.toUpperCase()} artifact...`\n );\n\n const result = await withMcp(mcpConfig, (client) =>\n client.callTool<CreateResult>(\"artifact-create\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.sessionId) {\n const message = result.reason || result.error || \"Generation failed\";\n // Own-code failures carry recovery guidance (e.g. the upload_not_found\n // duplicate-artifact warning) — losing it at the CLI boundary would\n // strip exactly what the caller needs to retry correctly.\n throw apiError(result.nextSteps ? `${message}\\n${result.nextSteps}` : message, result);\n }\n\n const playgroundUrl = result.playgroundUrl || `${PLAYGROUND_BASE}/${result.sessionId}`;\n\n progress.succeed(\"Artifact created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({ sessionId: result.sessionId, playgroundUrl });\n if (result.gitRemoteUrl) {\n console.log(` ${chalk.cyan(`git clone ${result.gitRemoteUrl}`)}`);\n console.log();\n console.log(\" Commit and push to update the live artifact.\");\n if (result.expiresAt) {\n console.log(\n ` The URL embeds a token that expires at ${result.expiresAt} and cannot be renewed;\\n` +\n ` run ${chalk.cyan(`anima get-git-token ${result.sessionId}`)} and ` +\n `${chalk.cyan(\"git remote set-url origin <new url>\")} to keep pushing.`\n );\n }\n console.log(\" Treat the URL as a secret — it grants access to this artifact.\");\n console.log();\n } else if (type === \"empty\") {\n console.log(\n ` Next: anima get-git-token ${result.sessionId} — then git clone, add your code, and git push.`\n );\n console.log();\n }\n if (type === \"import\" && result.fileCount !== undefined) {\n console.log(` ${result.fileCount} files committed (framework: ${result.framework ?? \"detected server-side\"}).`);\n if (result.skippedFiles?.length) {\n console.log(` Skipped (blocked/hidden): ${result.skippedFiles.join(\", \")}`);\n }\n if (result.notes) {\n console.log(` Note: ${result.notes}`);\n }\n console.log();\n }\n } else {\n outputResult(mode, {\n success: true,\n sessionId: result.sessionId,\n playgroundUrl,\n ...(result.gitRemoteUrl\n ? { gitRemoteUrl: result.gitRemoteUrl, access: result.access, expiresAt: result.expiresAt }\n : {}),\n ...(result.framework ? { framework: result.framework } : {}),\n ...(result.fileCount !== undefined ? { fileCount: result.fileCount } : {}),\n ...(result.skippedFiles?.length ? { skippedFiles: result.skippedFiles } : {}),\n ...(result.notes ? { notes: result.notes } : {}),\n ...(result.nextSteps ? { nextSteps: result.nextSteps } : {}),\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\nfunction validateCreateOptions(type: CreateType, opts: Record<string, string>): void {\n if (![\"empty\", \"import\", \"p2c\", \"l2c\", \"f2c\"].includes(type)) {\n throw validationError(`Invalid type \"${type}\". Must be empty, import, p2c, l2c, or f2c.`);\n }\n if (type === \"p2c\" && !opts.prompt) {\n throw validationError(\"--prompt is required for p2c type\");\n }\n if (type === \"l2c\" && !opts.url) {\n throw validationError(\"--url is required for l2c type\");\n }\n if (type === \"f2c\" && !opts.fileKey) {\n throw validationError(\"--file-key is required for f2c type\");\n }\n if (type === \"empty\" && !opts.framework) {\n throw validationError(\n \"--framework is required for type empty — html for plain HTML/CSS/JS, react for React (declare react if you will push React code)\"\n );\n }\n if (type === \"import\" && !opts.from) {\n throw validationError(\"--from <folder|zip> is required for type import — the path to the project to import\");\n }\n if (type !== \"import\" && opts.from) {\n throw validationError(\"--from is only valid with -t import\");\n }\n}\n\nfunction resolveFigmaToken(opts: Record<string, string>, stored?: string): string {\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || stored;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required for f2c. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n return figmaToken;\n}\n\nfunction buildCreateArgs(type: CreateType, opts: Record<string, string>): Record<string, unknown> {\n // empty: framework is required (validated above) — the caller declares what\n // they'll push. import: framework only when explicit — the server detects\n // it from package.json otherwise. The files/zipUploadId for import are\n // attached later by the action (they may need the upload leg first).\n if (type === \"empty\" || type === \"import\") {\n return {\n type,\n ...(opts.framework ? { framework: opts.framework } : {}),\n ...(opts.name ? { name: opts.name } : {}),\n };\n }\n\n // Generation types: html is the default — aligned with the MCP\n // artifact-create surface. Only html and react are supported.\n const framework = opts.framework ?? \"html\";\n // Default language to typescript when framework is react (matches the web import form).\n const language = opts.language ?? (framework === \"react\" ? \"typescript\" : undefined);\n\n const artifactType = opts.artifactType;\n const args: Record<string, unknown> = {\n type,\n // framework describes how to build an app; a document has none.\n ...(artifactType === \"markdown\" ? {} : { framework }),\n ...(artifactType ? { artifactType } : {}),\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n switch (type) {\n case \"p2c\":\n args.prompt = opts.prompt;\n if (opts.guidelines) args.guidelines = opts.guidelines;\n break;\n case \"l2c\":\n args.url = opts.url;\n break;\n case \"f2c\": {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n args.fileKey = fileKey;\n args.nodesId = nodesId;\n break;\n }\n }\n\n return args;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".config\", \"anima\");\nconst CREDENTIALS_FILE = path.join(CONFIG_DIR, \"credentials.json\");\n\n/**\n * A scoped, revocable identity from one of the OAuth doors. Every field is\n * present — agentSession.ts refuses a partial one — so an agent credential that\n * cannot renew itself is not representable.\n */\nexport type AgentCredential = {\n tokenType: \"agent\";\n token: string;\n teamId: string;\n agentId: string;\n expiresAt: string; // ISO — when `token` stops being accepted\n // Single use — see refresh.ts. Exchanged for a new pair at expiry.\n refreshToken: string;\n refreshExpiresAt: string; // ISO — the refresh token's own idle deadline\n};\n\n/**\n * A personal API token pasted in with `anima auth --token`. It carries the\n * user's full authority rather than a consented scope, is minted outside any\n * OAuth door, and has nothing to renew. Named `account` to match how the API\n * classifies the same credential (`TokenClass` in public-shared).\n */\nexport type AccountCredential = {\n tokenType: \"account\";\n token: string;\n teamId?: string;\n};\n\n/** Not an Anima credential — it accompanies either kind, or stands alone. */\ntype FigmaCredential = { figmaToken?: string };\n\nexport type Credentials = FigmaCredential & (AgentCredential | AccountCredential);\n\n/**\n * What the credential file holds, narrowed. `absent` and `malformed` are kept\n * apart for the same reason the backend's `classifyToken` separates `unknown`\n * from `malformed`: \"you have never logged in\" and \"your credential file is\n * damaged\" deserve different answers.\n */\nexport type StoredCredentials =\n | { kind: \"agent\"; credential: AgentCredential; figmaToken?: string }\n | { kind: \"account\"; credential: AccountCredential; figmaToken?: string }\n | { kind: \"figma-only\"; figmaToken: string }\n | { kind: \"absent\" }\n | { kind: \"malformed\" };\n\n/** Read and narrow. The single place that decides what the file on disk is. */\nexport function classifyCredentials(): StoredCredentials {\n let parsed: Record<string, unknown>;\n try {\n if (!fs.existsSync(CREDENTIALS_FILE)) return { kind: \"absent\" };\n parsed = JSON.parse(fs.readFileSync(CREDENTIALS_FILE, \"utf-8\"));\n } catch {\n return { kind: \"malformed\" };\n }\n\n const figmaToken = typeof parsed.figmaToken === \"string\" ? parsed.figmaToken : undefined;\n if (typeof parsed.token !== \"string\") {\n return figmaToken ? { kind: \"figma-only\", figmaToken } : { kind: \"absent\" };\n }\n\n // An agent credential is only usable if it carries everything renewal needs;\n // anything short of that is damaged rather than a different kind.\n if (parsed.tokenType === \"agent\") {\n const required = [\"teamId\", \"agentId\", \"expiresAt\", \"refreshToken\", \"refreshExpiresAt\"] as const;\n if (required.some((field) => typeof parsed[field] !== \"string\")) {\n return { kind: \"malformed\" };\n }\n return { kind: \"agent\", credential: parsed as unknown as AgentCredential, figmaToken };\n }\n\n return {\n kind: \"account\",\n credential: {\n tokenType: \"account\",\n token: parsed.token,\n teamId: typeof parsed.teamId === \"string\" ? parsed.teamId : undefined,\n },\n figmaToken,\n };\n}\n\n/** Convenience over `classifyCredentials` for callers that only need the credential. */\nexport function readCredentials(): Credentials | null {\n const stored = classifyCredentials();\n if (stored.kind !== \"agent\" && stored.kind !== \"account\") return null;\n return { ...stored.credential, ...(stored.figmaToken ? { figmaToken: stored.figmaToken } : {}) };\n}\n\n/** Replace the Anima credential, keeping the Figma token that may sit beside it. */\nexport function saveCredential(credential: AgentCredential | AccountCredential): void {\n const figmaToken = readCredentials()?.figmaToken;\n write({ ...credential, ...(figmaToken ? { figmaToken } : {}) });\n}\n\n/** The Figma token accompanies either credential kind, so it merges on its own. */\nexport function saveFigmaToken(figmaToken: string): void {\n const existing = readCredentials();\n write({ ...(existing ?? {}), figmaToken } as Credentials);\n}\n\nfunction write(credentials: Credentials): void {\n const merged: Record<string, unknown> = { ...credentials };\n for (const key of Object.keys(merged)) {\n if (merged[key] === undefined) delete merged[key];\n }\n\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n // Write to a sibling temp file and rename: a crash mid-write must not leave a\n // truncated file, because losing the refresh token means a full re-login.\n const tmp = `${CREDENTIALS_FILE}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + \"\\n\", { mode: 0o600 });\n fs.renameSync(tmp, CREDENTIALS_FILE);\n}\n\nexport function deleteCredentials(): boolean {\n try {\n if (fs.existsSync(CREDENTIALS_FILE)) {\n fs.unlinkSync(CREDENTIALS_FILE);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Full logout: remove every stored token (all live in credentials.json) and\n * the config directory itself when nothing else is left in it. Returns whether\n * any credentials were present.\n */\nexport function clearStorage(): boolean {\n const had = deleteCredentials();\n try {\n if (fs.existsSync(CONFIG_DIR) && fs.readdirSync(CONFIG_DIR).length === 0) {\n fs.rmdirSync(CONFIG_DIR);\n }\n } catch {\n /* leaving an empty dir behind is harmless */\n }\n return had;\n}\n\nexport function getCredentialsPath(): string {\n return CREDENTIALS_FILE;\n}\n\n/**\n * Extract the defaultTeamId from a JWT token payload (base64-decoded, no verification).\n * Returns undefined if extraction fails.\n */\nexport function extractTeamIdFromJWT(token: string): string | undefined {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf-8\")\n );\n return payload.defaultTeamId ?? undefined;\n } catch {\n return undefined;\n }\n}\n","/** Decode a JWT payload without verification (display/bookkeeping only). */\nexport function decodeJwtPayload(token: string): Record<string, unknown> | undefined {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n return JSON.parse(Buffer.from(parts[1], \"base64url\").toString(\"utf-8\"));\n } catch {\n return undefined;\n }\n}\n","export const EXIT_CODES = {\n SUCCESS: 0,\n API_ERROR: 1,\n AUTH_ERROR: 2,\n VALIDATION_ERROR: 3,\n TIMEOUT: 4,\n} as const;\n\nexport type ErrorCode =\n | \"AUTH_REQUIRED\"\n | \"AUTH_INVALID\"\n | \"VALIDATION_ERROR\"\n | \"API_ERROR\"\n | \"TIMEOUT\"\n | \"CONNECTION_ERROR\";\n\nexport class CliError extends Error {\n code: ErrorCode;\n exitCode: number;\n detail?: unknown;\n\n constructor(\n code: ErrorCode,\n message: string,\n exitCode: number,\n detail?: unknown\n ) {\n super(message);\n this.name = \"CliError\";\n this.code = code;\n this.exitCode = exitCode;\n this.detail = detail;\n }\n}\n\nexport function authError(message: string): CliError {\n return new CliError(\"AUTH_REQUIRED\", message, EXIT_CODES.AUTH_ERROR);\n}\n\nexport function validationError(message: string, detail?: unknown): CliError {\n return new CliError(\n \"VALIDATION_ERROR\",\n message,\n EXIT_CODES.VALIDATION_ERROR,\n detail\n );\n}\n\nexport function apiError(message: string, detail?: unknown): CliError {\n return new CliError(\"API_ERROR\", message, EXIT_CODES.API_ERROR, detail);\n}\n\nexport function timeoutError(): CliError {\n return new CliError(\n \"TIMEOUT\",\n \"Request timed out. Generation can take 3-7 minutes. Try increasing --timeout.\",\n EXIT_CODES.TIMEOUT\n );\n}\n","import { decodeJwtPayload } from \"./jwt.js\";\nimport { saveCredential } from \"./store.js\";\nimport { authError } from \"../api/errors.js\";\n\n/**\n * What a door hands back once a human has approved. Every field is required:\n * the token endpoint mints them together, so a missing one means the server is\n * not the one this CLI targets — better caught at login than a day later, when\n * renewal silently does not happen.\n */\nexport type AgentSession = {\n token: string;\n teamId: string;\n agentId: string;\n expiresAt: string;\n refreshToken: string;\n refreshExpiresAt: string;\n};\n\nfunction required<T>(value: T | undefined, field: string): T {\n if (value === undefined) {\n throw authError(\n `The server's token response is missing \\`${field}\\`. Check --api-url points at an Anima API that issues agent credentials.`\n );\n }\n return value;\n}\n\n/**\n * Build a session from a token-endpoint response, or fail naming what was\n * missing. `carriedOver` supplies the refresh pair a rotation response may\n * legally omit (RFC 6749 §6: no replacement means keep using the presented\n * one); a login response has nothing to carry over, so a missing field there\n * is an error.\n */\nexport function agentSessionFromTokenResponse(\n body: Record<string, unknown>,\n carriedOver?: { refreshToken: string; refreshExpiresAt: string }\n): AgentSession {\n const token = typeof body.access_token === \"string\" ? body.access_token : undefined;\n const claims = decodeJwtPayload(required(token, \"access_token\"));\n\n return {\n token: token!,\n teamId: required(typeof claims?.team_id === \"string\" ? claims.team_id : undefined, \"team_id\"),\n agentId: required(typeof claims?.agent_id === \"string\" ? claims.agent_id : undefined, \"agent_id\"),\n expiresAt: required(\n typeof claims?.exp === \"number\" ? new Date(claims.exp * 1000).toISOString() : undefined,\n \"exp\"\n ),\n refreshToken: required(\n typeof body.refresh_token === \"string\" ? body.refresh_token : carriedOver?.refreshToken,\n \"refresh_token\"\n ),\n refreshExpiresAt: required(\n typeof body.refresh_expires_in === \"number\"\n ? new Date(Date.now() + body.refresh_expires_in * 1000).toISOString()\n : carriedOver?.refreshExpiresAt,\n \"refresh_expires_in\"\n ),\n };\n}\n\n/** Every door stores the same shape, so the rest of the CLI cannot tell them apart. */\nexport function persistAgentSession(session: AgentSession): void {\n saveCredential({ tokenType: \"agent\", ...session });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Opt-in debug log. When a command is given `--log-file <path>` (or the\n * ANIMA_LOG_FILE env var is set), every network step appends one JSON line to\n * that file. Off by default and a no-op until enabled, so it never touches\n * stdout/stderr. Secret-bearing keys (tokens, auth headers) are redacted.\n *\n * Writes are synchronous (appendFileSync) so nothing is lost when a command\n * ends with process.exit() on an error path.\n */\n\nlet logPath: string | null = null;\n\nconst REDACT_KEY = /token|authorization|secret|password|_auth|api[-_]?key/i;\nconst REDACTED = \"***REDACTED***\";\n\nexport function initLogger(filePath?: string): void {\n const target = filePath || process.env.ANIMA_LOG_FILE;\n if (!target || logPath) return;\n logPath = path.resolve(target);\n fs.mkdirSync(path.dirname(logPath), { recursive: true });\n logEvent(\"log_started\", { pid: process.pid, argv: process.argv.slice(2) });\n}\n\nexport function logEvent(event: string, data?: Record<string, unknown>): void {\n if (!logPath) return;\n const entry = { ts: new Date().toISOString(), event, ...(data ? redact(data) : {}) };\n fs.appendFileSync(logPath, JSON.stringify(entry) + \"\\n\");\n}\n\nfunction redact(value: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (REDACT_KEY.test(key)) {\n out[key] = REDACTED;\n } else if (val && typeof val === \"object\" && !Array.isArray(val)) {\n out[key] = redact(val as Record<string, unknown>);\n } else {\n out[key] = val;\n }\n }\n return out;\n}\n","import { readCredentials, saveCredential, clearStorage } from \"./store.js\";\nimport { agentSessionFromTokenResponse, type AgentSession } from \"./agentSession.js\";\nimport { authError, apiError } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * Exchange a refresh token for a new access token (RFC 6749 §6).\n *\n * Refresh tokens are single use: every exchange returns a new one, and\n * presenting a spent one outside the server's rotation leeway revokes the whole\n * family. So the new pair is persisted before it is returned.\n */\nconst REFRESH_GRANT_TYPE = \"refresh_token\";\n\n/**\n * An OAuth error is `{error: \"code\", error_description}` (RFC 6749 §5.2), but a\n * misdirected request can land on something that answers in its own shape — a\n * framework validation error, a proxy, an older API. Read both without letting\n * an object reach the message, where it prints as `[object Object]` and tells\n * the operator nothing.\n */\nfunction readFailure(body: Record<string, unknown>): { code: string | null; message: string | null } {\n const raw = body.error;\n const nested = typeof raw === \"object\" && raw !== null ? (raw as Record<string, unknown>) : null;\n const code =\n typeof raw === \"string\"\n ? raw\n : typeof nested?.code === \"string\"\n ? nested.code\n : typeof nested?.error === \"string\"\n ? nested.error\n : null;\n\n const described = typeof body.error_description === \"string\" ? body.error_description : null;\n const message = described ?? (typeof raw === \"string\" ? raw : raw == null ? null : JSON.stringify(raw));\n return { code, message };\n}\n\nexport async function refreshAccessToken(\n apiUrl: string,\n carriedOver: { refreshToken: string; refreshExpiresAt: string },\n fetchFn: typeof fetch = fetch\n): Promise<AgentSession> {\n const base = apiUrl.replace(/\\/$/, \"\");\n const response = await fetchFn(`${base}/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: REFRESH_GRANT_TYPE,\n refresh_token: carriedOver.refreshToken,\n }).toString(),\n });\n\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const failure = readFailure(body);\n logEvent(\"refresh_token_response\", { status: response.status, error: failure.code });\n\n if (!response.ok || typeof body.access_token !== \"string\") {\n // Dead credential: agent revoked, consent expired, or the token already\n // replaced. Nothing retryable, so drop the pair rather than leave one that\n // fails on every command.\n if (failure.code === \"invalid_grant\") {\n clearStorage();\n throw authError(`${failure.message ?? \"Your credentials are no longer valid\"}\\nRun: anima login`);\n }\n throw apiError(\n `Could not refresh credentials (HTTP ${response.status})${failure.message ? `: ${failure.message}` : \"\"}`\n );\n }\n\n const session = agentSessionFromTokenResponse(body, carriedOver);\n saveCredential({ tokenType: \"agent\", ...session });\n return session;\n}\n\n/**\n * Revoke the stored refresh token server-side (RFC 7009), killing every\n * credential descended from the same consent. Best effort: logout must clear\n * the machine even when the server is unreachable.\n */\nexport async function revokeStoredRefreshToken(\n apiUrl: string,\n fetchFn: typeof fetch = fetch\n): Promise<boolean> {\n const creds = readCredentials();\n if (creds?.tokenType !== \"agent\") return false;\n\n try {\n const response = await fetchFn(`${apiUrl.replace(/\\/$/, \"\")}/oauth/revoke`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ token: creds.refreshToken, token_type_hint: \"refresh_token\" }).toString(),\n });\n logEvent(\"revoke_response\", { status: response.status });\n return response.ok;\n } catch (err) {\n logEvent(\"revoke_failed\", { error: err instanceof Error ? err.message : String(err) });\n return false;\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\n/**\n * Persistent, non-secret CLI preferences (e.g. a default API URL for local\n * development). Kept separate from credentials.json so `anima logout` never\n * wipes your machine config. Manage it with `anima config`.\n */\n\nconst CONFIG_DIR = path.join(os.homedir(), \".config\", \"anima\");\nconst CONFIG_FILE = path.join(CONFIG_DIR, \"config.json\");\n\nexport const DEFAULT_API_URL = \"https://api.agentgrid.io\";\n\nexport type Config = {\n apiUrl?: string;\n};\n\n/** User-facing config keys (kebab) mapped to their stored (camel) field. */\nexport const CONFIG_KEYS = {\n \"api-url\": \"apiUrl\",\n} as const satisfies Record<string, keyof Config>;\n\nexport type ConfigKey = keyof typeof CONFIG_KEYS;\n\nexport function isConfigKey(key: string): key is ConfigKey {\n return key in CONFIG_KEYS;\n}\n\nexport function configKeys(): ConfigKey[] {\n return Object.keys(CONFIG_KEYS) as ConfigKey[];\n}\n\nexport function readConfig(): Config {\n try {\n if (!fs.existsSync(CONFIG_FILE)) return {};\n const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, \"utf-8\"));\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n return {};\n }\n}\n\nexport function setConfig(key: ConfigKey, value: string): void {\n const merged = { ...readConfig(), [CONFIG_KEYS[key]]: value };\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + \"\\n\");\n}\n\n/** Remove one key; returns whether it was set. */\n/** Remove the whole config file (used by logout — full machine reset). */\nexport function deleteConfig(): boolean {\n try {\n if (!fs.existsSync(CONFIG_FILE)) return false;\n fs.unlinkSync(CONFIG_FILE);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function unsetConfig(key: ConfigKey): boolean {\n const config = readConfig();\n const field = CONFIG_KEYS[key];\n if (!(field in config)) return false;\n delete config[field];\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + \"\\n\");\n return true;\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n\n/**\n * Resolve the API base URL. Precedence: explicit flag → ANIMA_API_URL env →\n * stored config → built-in default.\n */\nexport function resolveApiUrl(flagValue?: string): string {\n return flagValue || process.env.ANIMA_API_URL || readConfig().apiUrl || DEFAULT_API_URL;\n}\n","import { classifyCredentials, getCredentialsPath } from \"./store.js\";\nimport { refreshAccessToken } from \"./refresh.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { authError } from \"../api/errors.js\";\n\nexport type ResolvedAuth = {\n token: string;\n teamId?: string;\n figmaToken?: string;\n source: \"env\" | \"file\";\n tokenType?: \"agent\" | \"account\";\n};\n\n/**\n * Renew this far ahead of expiry so a command that takes a while to run does\n * not have its token die mid-flight.\n */\nconst RENEW_BEFORE_EXPIRY_MS = 60_000;\n\nfunction needsRenewal(expiresAt: string | undefined): boolean {\n if (!expiresAt) return false;\n const expiry = new Date(expiresAt).getTime();\n return Number.isNaN(expiry) || expiry - Date.now() <= RENEW_BEFORE_EXPIRY_MS;\n}\n\n/**\n * Resolve the credential for an API call, renewing it when the stored access\n * token is at or near expiry.\n *\n * `apiUrlOverride` should be the command's `--api-url` when it has one, so a\n * renewal targets the same server the request will.\n */\nexport async function resolveAuth(apiUrlOverride?: string): Promise<ResolvedAuth> {\n const stored = classifyCredentials();\n\n // 1. Environment variable (primary — what AI tools use). Nothing to renew:\n // this is a long-lived personal token supplied from outside.\n const envToken = process.env.ANIMA_API_TOKEN;\n if (envToken) {\n return {\n token: envToken,\n teamId: process.env.ANIMA_TEAM_ID,\n figmaToken: process.env.FIGMA_TOKEN || (\"figmaToken\" in stored ? stored.figmaToken : undefined),\n source: \"env\",\n };\n }\n\n // 2. Stored credentials file\n const figmaToken = process.env.FIGMA_TOKEN || (\"figmaToken\" in stored ? stored.figmaToken : undefined);\n\n if (stored.kind === \"agent\") {\n const { credential } = stored;\n if (needsRenewal(credential.expiresAt)) {\n const renewed = await refreshAccessToken(resolveApiUrl(apiUrlOverride), {\n refreshToken: credential.refreshToken,\n refreshExpiresAt: credential.refreshExpiresAt,\n });\n return { token: renewed.token, teamId: renewed.teamId, figmaToken, source: \"file\", tokenType: \"agent\" };\n }\n return {\n token: credential.token,\n teamId: credential.teamId,\n figmaToken,\n source: \"file\",\n tokenType: \"agent\",\n };\n }\n\n if (stored.kind === \"account\") {\n return {\n token: stored.credential.token,\n teamId: stored.credential.teamId,\n figmaToken,\n source: \"file\",\n tokenType: \"account\",\n };\n }\n\n if (stored.kind === \"malformed\") {\n throw authError(\n `Your credentials file is damaged or incomplete (${getCredentialsPath()}). Run: anima login`\n );\n }\n\n // 3. No token found\n throw authError(\"No credentials found. Run: anima login\\n(or set the ANIMA_API_TOKEN env var)\");\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { CallToolResultSchema, ErrorCode } from \"@modelcontextprotocol/sdk/types.js\";\nimport { apiError, timeoutError, CliError } from \"./errors.js\";\nimport { logEvent } from \"../output/log.js\";\nimport { version } from \"../version.js\";\n\n/**\n * The CLI talks to AgentGrid only through the MCP endpoint (`/v1/mcp`), the single\n * governed surface (see anima-design-to-code docs/grids/DECISIONS.md \"D47\").\n * Every command runs a tool through this client — there is no other transport.\n */\n\nconst MCP_PATH = \"/v1/mcp\";\n// MCP clientInfo version tracks package.json so server logs see the real release.\nconst CLIENT_INFO = { name: \"anima-cli\", version };\n\nexport type McpConfig = {\n apiBaseUrl: string;\n token: string;\n teamId?: string;\n /** Sent as X-Figma-Token; f2c tools read it from the header, not the args. */\n figmaToken?: string;\n};\n\n/** Progress reported by long-running tools (generation, deploy). */\nexport type ToolProgress = { progress: number; total?: number; message?: string };\n\nexport type CallToolOptions = {\n onProgress?: (p: ToolProgress) => void;\n /** Idle timeout; reset on each progress notification so long jobs don't trip it. */\n timeoutMs?: number;\n};\n\nconst DEFAULT_TIMEOUT_MS = 600_000;\n\nexport class AnimaMcpClient {\n #client: Client;\n #transport: StreamableHTTPClientTransport;\n #url: string;\n\n constructor(config: McpConfig) {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${config.token}`,\n };\n if (config.teamId) headers[\"X-Team-Id\"] = config.teamId;\n if (config.figmaToken) headers[\"X-Figma-Token\"] = config.figmaToken;\n\n this.#url = new URL(MCP_PATH, config.apiBaseUrl).toString();\n this.#transport = new StreamableHTTPClientTransport(new URL(this.#url), {\n requestInit: { headers },\n });\n this.#client = new Client(CLIENT_INFO, { capabilities: {} });\n }\n\n async connect(): Promise<void> {\n logEvent(\"mcp_connect\", { url: this.#url });\n try {\n await this.#client.connect(this.#transport);\n } catch (err) {\n logEvent(\"mcp_connect_failed\", { url: this.#url, error: (err as Error)?.message });\n throw connectionError(err);\n }\n }\n\n /**\n * Call a tool and return its parsed result. Anima tools return a single JSON\n * text block; a `{ success: false }` payload is a normal result, so callers\n * still inspect `success` themselves.\n */\n async callTool<T = unknown>(\n name: string,\n args: Record<string, unknown>,\n options: CallToolOptions = {}\n ): Promise<T> {\n logEvent(\"mcp_tool_call\", { tool: name, arguments: args });\n let result;\n try {\n result = await this.#client.callTool(\n { name, arguments: args },\n CallToolResultSchema,\n {\n timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n resetTimeoutOnProgress: true,\n onprogress: options.onProgress\n ? (p) => options.onProgress!({ progress: p.progress, total: p.total, message: p.message })\n : undefined,\n }\n );\n } catch (err) {\n logEvent(\"mcp_tool_error\", { tool: name, error: (err as Error)?.message });\n if ((err as { code?: number })?.code === ErrorCode.RequestTimeout) {\n throw timeoutError();\n }\n throw err;\n }\n logEvent(\"mcp_tool_result\", { tool: name, isError: result.isError ?? false });\n\n const content = Array.isArray(result.content) ? result.content : [];\n const text = content.find((c): c is { type: \"text\"; text: string } => c.type === \"text\")?.text;\n\n if (result.isError) {\n throw apiError(text || \"MCP tool returned an error\");\n }\n if (!text) {\n throw apiError(\"MCP tool returned no text content\");\n }\n\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as T;\n }\n }\n\n async close(): Promise<void> {\n await this.#transport.close().catch(() => {});\n }\n}\n\n/** Connect, run `fn`, and always close the transport. */\nexport async function withMcp<T>(\n config: McpConfig,\n fn: (client: AnimaMcpClient) => Promise<T>\n): Promise<T> {\n const client = new AnimaMcpClient(config);\n await client.connect();\n try {\n return await fn(client);\n } finally {\n await client.close();\n }\n}\n\nfunction connectionError(err: unknown): CliError {\n const message = err instanceof Error ? err.message : String(err);\n return new CliError(\n \"CONNECTION_ERROR\",\n `Could not reach the AgentGrid MCP endpoint: ${message}`,\n 1\n );\n}\n","import { createRequire } from \"node:module\";\n\n// Single source for the CLI version: package.json. `../package.json` resolves\n// from src/ in dev and from dist/index.js in the published bundle — this file\n// must stay directly under src/ for that to hold.\nexport const { version } = createRequire(import.meta.url)(\"../package.json\") as { version: string };\n","export type OutputMode = \"json\" | \"pretty\";\n\nexport function detectOutputMode(flags: {\n json?: boolean;\n}): OutputMode {\n if (flags.json !== undefined) {\n return flags.json ? \"json\" : \"pretty\";\n }\n // Auto-detect: JSON when piped, pretty in TTY\n return process.stdout.isTTY ? \"pretty\" : \"json\";\n}\n\nexport function outputResult(mode: OutputMode, data: unknown): void {\n if (mode === \"json\") {\n process.stdout.write(JSON.stringify(data) + \"\\n\");\n }\n // Pretty mode output is handled inline by commands using chalk/ora\n}\n\nexport function outputError(\n mode: OutputMode,\n error: { code: string; message: string }\n): void {\n if (mode === \"json\") {\n process.stdout.write(\n JSON.stringify({ success: false, error }) + \"\\n\"\n );\n }\n // Pretty mode errors are handled inline by commands\n}\n","import ora, { type Ora } from \"ora\";\nimport type { OutputMode } from \"./formatter.js\";\n\nexport class ProgressReporter {\n #spinner: Ora | null = null;\n #mode: OutputMode;\n #startTime: number = 0;\n #verbose: boolean;\n\n constructor(mode: OutputMode, verbose: boolean = false) {\n this.#mode = mode;\n this.#verbose = verbose;\n }\n\n start(message: string): void {\n this.#startTime = Date.now();\n if (this.#mode === \"pretty\") {\n // A previous phase's spinner must be stopped first: an orphaned ora\n // interval keeps the event loop (and its repaints) alive forever.\n this.#spinner?.stop();\n this.#spinner = ora(message).start();\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"started\", message }) + \"\\n\");\n }\n }\n\n update(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.text = `${message} ${elapsed}`;\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"progress\", message }) + \"\\n\");\n }\n }\n\n succeed(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.succeed(`${message} ${elapsed}`);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"done\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n fail(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n this.#spinner.fail(message);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"error\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n #elapsed(): string {\n const ms = Date.now() - this.#startTime;\n const seconds = Math.floor(ms / 1000);\n if (seconds < 60) return `(${seconds}s)`;\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `(${minutes}m ${secs}s)`;\n }\n}\n","import chalk from \"chalk\";\n\nexport function printSuccess(message: string): void {\n console.log(chalk.green(\"✓\") + \" \" + message);\n}\n\nexport function printError(message: string): void {\n console.error(chalk.red(\"✗\") + \" \" + message);\n}\n\nexport function printInfo(message: string): void {\n console.log(chalk.blue(\"ℹ\") + \" \" + message);\n}\n\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(\"⚠\") + \" \" + message);\n}\n\nexport function printKeyValue(key: string, value: string): void {\n console.log(` ${chalk.gray(key + \":\")} ${value}`);\n}\n\nexport function printSessionResult(result: {\n sessionId: string;\n playgroundUrl?: string;\n tokenUsage?: number;\n}): void {\n console.log();\n printSuccess(\"Artifact created successfully!\");\n printKeyValue(\"Session ID\", result.sessionId);\n if (result.playgroundUrl) {\n printKeyValue(\"Your artifact\", chalk.cyan.underline(result.playgroundUrl));\n }\n if (result.tokenUsage) {\n printKeyValue(\"Token usage\", result.tokenUsage.toLocaleString());\n }\n console.log();\n}\n\nexport function printDeployResult(result: { url?: string }): void {\n console.log();\n printSuccess(\"Published successfully!\");\n if (result.url) {\n printKeyValue(\"Live URL\", chalk.cyan.underline(result.url));\n }\n console.log();\n}\n\nexport function printFilesWritten(outputDir: string, count: number): void {\n console.log();\n printSuccess(`${count} files written to ${chalk.cyan(outputDir)}`);\n console.log();\n}\n","/**\n * Parse a Figma URL to extract fileKey and nodeId.\n *\n * Supported formats:\n * - https://www.figma.com/file/ABC123/FileName?node-id=42-15\n * - https://www.figma.com/design/ABC123/FileName?node-id=42-15\n * - https://figma.com/file/ABC123/FileName?node-id=42%3A15\n * - Just a fileKey string\n */\nexport function parseFigmaUrl(input: string): {\n fileKey: string;\n nodeId?: string;\n} {\n // If it doesn't look like a URL, treat as a raw file key\n if (!input.includes(\"figma.com\")) {\n return { fileKey: input };\n }\n\n try {\n const url = new URL(input);\n const pathParts = url.pathname.split(\"/\").filter(Boolean);\n\n // Expected format: /file/KEY/name or /design/KEY/name\n const typeIndex = pathParts.findIndex(\n (p) => p === \"file\" || p === \"design\"\n );\n if (typeIndex === -1 || typeIndex + 1 >= pathParts.length) {\n throw new Error(\"Could not find file key in Figma URL\");\n }\n\n const fileKey = pathParts[typeIndex + 1];\n const nodeIdParam = url.searchParams.get(\"node-id\");\n\n let nodeId: string | undefined;\n if (nodeIdParam) {\n // Convert dash format (42-15) to colon format (42:15)\n nodeId = nodeIdParam.replace(/-/g, \":\");\n }\n\n return { fileKey, nodeId };\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"file key\")) {\n throw err;\n }\n throw new Error(`Invalid Figma URL: ${input}`);\n }\n}\n\n/**\n * Normalize a node ID: convert dash format to colon format.\n * \"42-15\" -> \"42:15\"\n */\nexport function normalizeNodeId(nodeId: string): string {\n return nodeId.replace(/-/g, \":\");\n}\n","import { readdirSync, readFileSync, statSync } from \"fs\";\nimport { join, relative, extname } from \"path\";\nimport AdmZip from \"adm-zip\";\n\n/**\n * Collect a local project for `create -t import --from <path>`.\n *\n * Two transports, mirroring the server's contract:\n * - inline: small, text-only projects → `files` map on artifact-create\n * - zip: anything with binaries or over the inline caps, or a .zip given\n * directly → artifact-get_zip_upload_url + PUT + zipUploadId\n */\n\nconst SKIPPED_DIRS = new Set([\".git\", \"node_modules\", \"dist\", \"build\", \".next\", \"out\", \"coverage\", \".turbo\", \".cache\"]);\n\nconst BINARY_EXTENSIONS = new Set([\n \".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".ico\", \".bmp\",\n \".woff\", \".woff2\", \".ttf\", \".otf\", \".eot\",\n \".mp4\", \".webm\", \".mp3\", \".wav\", \".ogg\",\n \".zip\", \".tar\", \".gz\", \".pdf\", \".wasm\",\n]);\n\n/** Server-side inline caps (kept in sync with artifact-create). */\nconst MAX_INLINE_FILES = 1000;\nconst MAX_INLINE_BYTES = 10 * 1024 * 1024;\n\nexport type ProjectSource =\n | { kind: \"files\"; files: Record<string, string>; fileCount: number }\n | { kind: \"zip\"; buffer: Buffer; reason: string };\n\nfunction walk(root: string, dir: string, out: string[]): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (!SKIPPED_DIRS.has(entry.name)) walk(root, join(dir, entry.name), out);\n } else if (entry.isFile()) {\n out.push(relative(root, join(dir, entry.name)));\n }\n }\n}\n\nfunction zipFolder(root: string): Buffer {\n const zip = new AdmZip();\n zip.addLocalFolder(root, \"\", (entryPath) => {\n const segments = entryPath.split(/[\\\\/]/);\n return !segments.some((segment) => SKIPPED_DIRS.has(segment));\n });\n return zip.toBuffer();\n}\n\nfunction isProbablyBinary(path: string, buffer: Buffer): boolean {\n if (BINARY_EXTENSIONS.has(extname(path).toLowerCase())) return true;\n return buffer.includes(0);\n}\n\n/**\n * Read a folder or .zip into the transport the server expects.\n * Never sends binaries inline: any binary file, or exceeding the inline caps,\n * switches the whole project to the zip transport.\n */\nexport function collectProjectSource(fromPath: string): ProjectSource {\n const stats = statSync(fromPath);\n\n if (stats.isFile()) {\n if (extname(fromPath).toLowerCase() !== \".zip\") {\n throw new Error(`--from must be a folder or a .zip file, got: ${fromPath}`);\n }\n return { kind: \"zip\", buffer: readFileSync(fromPath), reason: \"zip file given\" };\n }\n\n const paths: string[] = [];\n walk(fromPath, fromPath, paths);\n if (paths.length === 0) {\n throw new Error(`--from folder is empty: ${fromPath}`);\n }\n if (paths.length > MAX_INLINE_FILES) {\n return { kind: \"zip\", buffer: zipFolder(fromPath), reason: `${paths.length} files exceeds the inline limit` };\n }\n\n const files: Record<string, string> = {};\n let totalBytes = 0;\n for (const path of paths) {\n const buffer = readFileSync(join(fromPath, path));\n if (isProbablyBinary(path, buffer)) {\n return { kind: \"zip\", buffer: zipFolder(fromPath), reason: `binary file present (${path})` };\n }\n totalBytes += buffer.length;\n if (totalBytes > MAX_INLINE_BYTES) {\n return { kind: \"zip\", buffer: zipFolder(fromPath), reason: \"project exceeds the inline size limit\" };\n }\n // Normalize Windows separators — the server rejects backslashes\n files[path.split(\"\\\\\").join(\"/\")] = buffer.toString(\"utf8\");\n }\n\n return { kind: \"files\", files, fileCount: paths.length };\n}\n","/** Base for the user-facing playground link: `${BASE}/<sessionId>`. */\nexport const PLAYGROUND_BASE = \"https://dev.animaapp.com/chat\";\n\n/**\n * Parse a playground URL to extract the session ID.\n * Supported formats:\n * - https://dev.animaapp.com/chat/SESSION_ID\n * - https://app.agentgrid.io/artifacts/SESSION_ID\n * - Just a session ID string\n */\nexport function parsePlaygroundUrl(input: string): string {\n if (!input.includes(\"/\")) {\n return input;\n }\n\n try {\n const url = new URL(input);\n const parts = url.pathname.split(\"/\").filter(Boolean);\n // Expected: /chat/SESSION_ID or /artifacts/SESSION_ID — the session id is\n // the segment after either marker.\n const markerIndex = parts.findIndex((p) => p === \"chat\" || p === \"artifacts\");\n if (markerIndex !== -1 && markerIndex + 1 < parts.length) {\n return parts[markerIndex + 1];\n }\n // Fallback: last path segment\n return parts[parts.length - 1];\n } catch {\n // Not a URL, treat as session ID\n return input;\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { PLAYGROUND_BASE } from \"../utils/playgroundUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `workspace-list_artifacts` MCP tool. Lists the team's artifacts\n * most-recently-updated first so an agent can resume existing work instead of\n * creating duplicates.\n */\n\ntype Artifact = {\n id?: string;\n name: string;\n type: \"app\" | \"markdown\" | \"asset\";\n sessionId?: string;\n updatedAt: string;\n registered: boolean;\n};\n\ntype ListArtifactsResult = {\n success: boolean;\n workspaceId?: string;\n artifacts?: Artifact[];\n truncated?: boolean;\n error?: string;\n reason?: string;\n};\n\nexport const listCommand = new Command(\"list\")\n .aliases([\"ls\", \"artifacts\"])\n .description(\n \"List your team's artifacts (most-recently-updated first) so you can resume existing work.\"\n )\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n try {\n const auth = await resolveAuth(opts.apiUrl);\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<ListArtifactsResult>(\"workspace-list_artifacts\", {})\n );\n\n if (!result.success) {\n const message = result.reason || result.error || \"Could not list artifacts\";\n throw apiError(message, result);\n }\n\n const artifacts = result.artifacts ?? [];\n logEvent(\"artifacts_listed\", { count: artifacts.length, truncated: result.truncated ?? false });\n\n if (mode === \"pretty\") {\n if (artifacts.length === 0) {\n console.log();\n console.log(\n \" No artifacts yet — create one with `create -t empty` or `create -t import`.\"\n );\n console.log();\n } else {\n console.log();\n for (const a of artifacts) {\n console.log(` ${chalk.bold(a.name)} ${chalk.gray(`(${a.type})`)}`);\n if (a.sessionId) {\n console.log(` ${chalk.gray(\"session:\")} ${a.sessionId}`);\n }\n console.log(` ${chalk.gray(\"updated:\")} ${formatUpdatedAt(a.updatedAt)}`);\n if (a.sessionId) {\n console.log(\n ` ${chalk.cyan.underline(`${PLAYGROUND_BASE}/${a.sessionId}`)}`\n );\n }\n console.log();\n }\n if (result.truncated) {\n console.log(\n chalk.yellow(\" The list was capped — some artifacts are not shown.\")\n );\n console.log();\n }\n }\n } else {\n outputResult(mode, {\n success: true,\n workspaceId: result.workspaceId,\n artifacts,\n truncated: result.truncated ?? false,\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\n/** Human-friendly \"x ago\" with the ISO timestamp in parentheses. */\nfunction formatUpdatedAt(iso: string): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) return iso;\n\n const seconds = Math.max(0, Math.round((Date.now() - then) / 1000));\n const relative =\n seconds < 60\n ? \"just now\"\n : seconds < 3600\n ? `${Math.floor(seconds / 60)}m ago`\n : seconds < 86400\n ? `${Math.floor(seconds / 3600)}h ago`\n : `${Math.floor(seconds / 86400)}d ago`;\n\n return `${relative} (${iso})`;\n}\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printDeployResult } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\nexport const publishCommand = new Command(\"publish\")\n .description(\"Deploy an artifact's app to a live public URL (1-3 min)\")\n .argument(\"<sessionId>\", \"Session ID from create command\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (sessionId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(\"Publishing...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n client.callTool<Record<string, unknown>>(\"artifact-publish\", { sessionId }, {\n onProgress: (p) => progress.update(p.message ?? \"Publishing...\"),\n })\n );\n\n if (!result.success) {\n throw new CliError(\n \"API_ERROR\",\n (result.error as string) || (result.reason as string) || \"Publish failed\",\n 1,\n result\n );\n }\n\n progress.succeed(\"Published!\");\n\n if (mode === \"pretty\") {\n printDeployResult({ url: result.liveUrl as string | undefined });\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n ...(result.liveUrl ? { liveUrl: result.liveUrl, subdomain: result.subdomain } : {}),\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printFilesWritten } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { writeFilesToDisk } from \"../utils/files.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\ntype CodegenResult = {\n success: boolean;\n sessionId?: string;\n files?: AnimaFiles;\n tokenUsage?: number;\n error?: string;\n reason?: string;\n};\n\nexport const codegenCommand = new Command(\"codegen\")\n .description(\"Convert Figma design to code files (no artifact)\")\n .requiredOption(\"--file-key <key>\", \"Figma file key or URL\")\n .option(\"--nodes <nodes>\", \"Figma node IDs, comma-separated\")\n .option(\"--figma-token <token>\", \"Figma personal access token (or set FIGMA_TOKEN env var)\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./generated\")\n .option(\"--framework <fw>\", \"react | html\", \"react\")\n .option(\"--styling <style>\", \"tailwind | plain_css\", \"tailwind\")\n .option(\"--language <lang>\", \"typescript | javascript\")\n .option(\"--ui-library <lib>\", \"mui | antd | shadcn | clean_react\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n: string) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n\n if (nodesId.length === 0) {\n throw validationError(\n \"No node IDs provided. Use --nodes or include node-id in the Figma URL.\"\n );\n }\n\n const auth = await resolveAuth(opts.apiUrl);\n\n // Resolve Figma token: flag > env var > stored credentials > error.\n // Sent via the X-Figma-Token header; the tool reads it from the header.\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || auth.figmaToken;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n\n // Default language to typescript when framework is react.\n const language = opts.language ?? (opts.framework === \"react\" ? \"typescript\" : undefined);\n\n const args: Record<string, unknown> = {\n fileKey,\n nodesId,\n framework: opts.framework,\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n progress.start(\"Generating code from Figma...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId, figmaToken },\n (client) =>\n client.callTool<CodegenResult>(\"codegen-figma_to_code\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.files) {\n throw apiError(result.reason || result.error || \"Code generation failed\", result);\n }\n\n const count = writeFilesToDisk(result.files, opts.output);\n\n progress.succeed(`Generated ${count} files`);\n\n if (mode === \"pretty\") {\n printFilesWritten(opts.output, count);\n } else {\n outputResult(mode, {\n success: true,\n output: opts.output,\n fileCount: count,\n sessionId: result.sessionId,\n tokenUsage: result.tokenUsage,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\n/**\n * Write generated files to disk.\n * Handles both code (text) and binary (base64-encoded) files.\n */\nexport function writeFilesToDisk(\n files: AnimaFiles,\n outputDir: string\n): number {\n // Create output directory\n fs.mkdirSync(outputDir, { recursive: true });\n\n let count = 0;\n\n const resolvedOutput = path.resolve(outputDir);\n\n for (const [filePath, fileContent] of Object.entries(files)) {\n const fullPath = path.resolve(outputDir, filePath);\n\n if (!fullPath.startsWith(resolvedOutput + path.sep)) {\n throw new Error(`Path traversal detected: ${filePath}`);\n }\n\n // Create parent directories\n const dirPath = path.dirname(fullPath);\n fs.mkdirSync(dirPath, { recursive: true });\n\n if (fileContent.isBinary) {\n const buffer = Buffer.from(fileContent.content, \"base64\");\n fs.writeFileSync(fullPath, buffer);\n } else {\n fs.writeFileSync(fullPath, fileContent.content, \"utf-8\");\n }\n\n count++;\n }\n\n return count;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { parsePlaygroundUrl } from \"../utils/playgroundUrl.js\";\nimport { parseGitTokenResponse } from \"../utils/gitToken.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `artifact-get_git_token` MCP tool — git is the only content\n * plane for artifact code. This mints a short-lived, repo-scoped git remote\n * URL; the caller runs git itself:\n *\n * git clone <gitRemoteUrl> # read (and edit locally)\n * git push # rw access: updates the live artifact\n * git remote set-url origin <url> # after expiry: point the clone at a fresh URL\n *\n * The token expires within an hour and cannot be renewed — re-run this command\n * for a fresh URL.\n */\nexport const getGitTokenCommand = new Command(\"get-git-token\")\n .description(\"Mint a short-lived git remote URL for an artifact (clone/push with git)\")\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const sessionId = parsePlaygroundUrl(artifactUrl);\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(\"Requesting git access...\");\n\n const response = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n client.callTool<unknown>(\"artifact-get_git_token\", { sessionId })\n );\n\n const grant = parseGitTokenResponse(response);\n logEvent(\"git_token_granted\", { sessionId, access: grant.access, expiresAt: grant.expiresAt });\n\n progress.succeed(`Git access granted (${grant.access === \"rw\" ? \"read-write\" : \"read-only\"})`);\n\n if (mode === \"pretty\") {\n console.log();\n console.log(` ${chalk.cyan(`git clone ${grant.gitRemoteUrl}`)}`);\n console.log();\n if (grant.access === \"rw\") {\n console.log(\" Commit and push to update the live artifact.\");\n } else {\n console.log(\" Read-only: cloning works, pushing will be rejected.\");\n }\n if (grant.expiresAt) {\n console.log(\n ` The URL embeds a token that expires at ${grant.expiresAt} and cannot be renewed;\\n` +\n ` re-run this command and ${chalk.cyan(\"git remote set-url origin <new url>\")} to keep pushing.`\n );\n }\n console.log(\" Treat the URL as a secret — it grants access to this artifact.\");\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n gitRemoteUrl: grant.gitRemoteUrl,\n access: grant.access,\n expiresAt: grant.expiresAt,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { apiError } from \"../api/errors.js\";\n\n/**\n * Parsed outcome of the `artifact-get_git_token` MCP tool.\n *\n * The tool returns JSON: `{ success, gitRemoteUrl, access, expiresAt }` on a\n * grant, or `{ success: false, error, reason }` on a denial. The MCP client\n * (api/mcp.ts) already JSON-parses tool text, so this receives the parsed\n * object — a string only arrives if that parse failed. The clone URL embeds a\n * short-lived access token scoped to the one artifact.\n */\nexport type GitTokenGrant = {\n gitRemoteUrl: string;\n access: \"ro\" | \"rw\";\n expiresAt?: string;\n};\n\nfunction preview(payload: unknown): string {\n const text = typeof payload === \"string\" ? payload : JSON.stringify(payload);\n return (text ?? String(payload)).slice(0, 200);\n}\n\nexport function parseGitTokenResponse(payload: unknown): GitTokenGrant {\n let value = payload;\n if (typeof value === \"string\") {\n try {\n value = JSON.parse(value);\n } catch {\n throw apiError(`Unexpected response from artifact-get_git_token: ${preview(payload)}`);\n }\n }\n\n if (value === null || typeof value !== \"object\") {\n throw apiError(`Unexpected response from artifact-get_git_token: ${preview(payload)}`);\n }\n\n const body = value as {\n success?: boolean;\n error?: string;\n reason?: string;\n gitRemoteUrl?: string;\n access?: string;\n expiresAt?: string;\n };\n\n if (body.success === false) {\n throw apiError(`Git access ${body.error ?? \"denied\"}: ${(body.reason ?? \"\").trim()}`);\n }\n\n if (!body.gitRemoteUrl) {\n throw apiError(`Unexpected response from artifact-get_git_token: ${preview(payload)}`);\n }\n\n return {\n gitRemoteUrl: body.gitRemoteUrl,\n access: body.access === \"rw\" ? \"rw\" : \"ro\",\n expiresAt: body.expiresAt,\n };\n}\n","import { Command } from \"commander\";\nimport { buildMcpConfig } from \"./login.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printInfo } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * Print the MCP server config for this API. The client authorizes itself, so\n * this needs no credentials and makes no network call.\n */\nexport const mcpConfigCommand = new Command(\"mcp-config\")\n .description(\"Print an MCP server config for your MCP client\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n\n try {\n const mcpConfig = buildMcpConfig(resolveApiUrl(opts.apiUrl));\n\n if (mode === \"pretty\") {\n printInfo(\"MCP server config (add to your MCP client):\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n console.log();\n printInfo(\"Your client will prompt you to authorize on first use.\");\n } else {\n outputResult(mode, { success: true, mcpConfig });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { loginWithDeviceFlow } from \"../auth/device.js\";\nimport { loginWithInvite, parseInvite } from \"../auth/invite.js\";\nimport { getCredentialsPath } from \"../auth/store.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { resolveApiUrl, setConfig, readConfig } from \"../config/store.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printSuccess, printError, printKeyValue, printInfo } from \"../output/pretty.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * `anima login` — connect this machine as a governed agent.\n *\n * Two doors, one credential store:\n * - Default: the OAuth device flow. The command prints a short code and a\n * verification URL; a human approves on any device — choosing which\n * workspaces and capabilities this agent gets — and the CLI picks up its\n * scoped token automatically.\n * - `--invite <url-or-code>`: redeem a pre-approved invite (the human already\n * consented in-app when minting it) — a single exchange, no human step and\n * no browser.\n * Either way the credentials renew themselves; logging in again with the same\n * agent name reconnects to the same agent identity.\n */\nexport const loginCommand = new Command(\"login\")\n .description(\"Log in via the device flow, or redeem a pre-approved invite with --invite\")\n .option(\"--invite <url-or-code>\", \"Redeem an invite link (…/invite/<code>.md) or bare code — no approval step\")\n .option(\"--client-name <name>\", \"How this CLI appears on the consent screen\", \"AgentGrid CLI\")\n .option(\"--no-open\", \"Do not try to open the verification page in a browser\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .option(\n \"--print-mcp-config\",\n \"After login, also print an MCP server config (URL only — the client authorizes itself) to paste into an MCP-capable agent\"\n )\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n if (opts.invite) {\n // The invite URL was minted on the API the human used, so its origin is\n // the right base unless the caller explicitly overrides it.\n const inviteOrigin = parseInvite(opts.invite).origin;\n const apiUrl = opts.apiUrl ? resolveApiUrl(opts.apiUrl) : (inviteOrigin ?? resolveApiUrl());\n\n try {\n const result = await loginWithInvite({ apiUrl, invite: opts.invite });\n // Persist the origin the invite was redeemed on: the token is only\n // valid THERE, so later commands (get-git-token, mcp-config, …) must\n // default to it instead of the built-in API URL.\n if (inviteOrigin && readConfig().apiUrl !== apiUrl) {\n setConfig(\"api-url\", apiUrl);\n }\n const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n printKeyValue(\"Agent\", result.agentId);\n printKeyValue(\"Team ID\", result.teamId);\n printKeyValue(\"Token expires\", result.expiresAt);\n printInfo(\"This is a scoped agent token — it acts within what was approved, and the team can revoke it.\");\n if (mcpConfig) {\n console.log();\n printInfo(\"MCP server config — your client will prompt to authorize on first use:\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"logged_in\",\n via: \"invite\",\n tokenType: \"agent\",\n agentId: result.agentId,\n teamId: result.teamId,\n expiresAt: result.expiresAt,\n ...(mcpConfig ? { mcpConfig } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n return;\n }\n\n const apiUrl = resolveApiUrl(opts.apiUrl);\n\n try {\n const result = await loginWithDeviceFlow({\n apiUrl,\n clientName: opts.clientName,\n onVerification: (info) => {\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"To connect, open the verification page and enter this code:\");\n console.log();\n console.log(` ${chalk.cyan.underline(info.verificationUri)}`);\n console.log();\n console.log(` ${chalk.bold.white(info.userCode)}`);\n console.log();\n printInfo(`Waiting for approval… (code expires in ${Math.round(info.expiresInSeconds / 60)} minutes)`);\n } else {\n // JSON mode: emit the verification info to stderr so a wrapping\n // agent can surface it to its human while stdout stays reserved\n // for the final result object.\n process.stderr.write(\n JSON.stringify({\n event: \"verification_required\",\n verificationUri: info.verificationUri,\n verificationUriComplete: info.verificationUriComplete,\n userCode: info.userCode,\n expiresIn: info.expiresInSeconds,\n }) + \"\\n\"\n );\n }\n\n // Best-effort convenience in a terminal; the printed URL + code are\n // the real path (the whole point of the flow is that THIS machine\n // may have no browser).\n if (mode === \"pretty\" && opts.open) {\n open(info.verificationUriComplete).catch(() => {});\n }\n },\n });\n\n const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n printKeyValue(\"Agent\", result.agentId);\n printKeyValue(\"Team ID\", result.teamId);\n printKeyValue(\"Token expires\", result.expiresAt);\n printInfo(\"This is a scoped agent token — it acts within what you approved, and your team can revoke it.\");\n if (mcpConfig) {\n console.log();\n printInfo(\"MCP server config — your client will prompt to authorize on first use:\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"logged_in\",\n tokenType: \"agent\",\n agentId: result.agentId,\n teamId: result.teamId,\n expiresAt: result.expiresAt,\n ...(mcpConfig ? { mcpConfig } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\n/**\n * A remote MCP server entry an MCP-capable agent can add to talk to Anima\n * directly (no CLI in the loop). Exact keys vary by client; this is the common\n * `mcpServers` shape. No credential: the client runs its own OAuth against the\n * server's advertised metadata and holds one it can renew, where a pasted\n * access token cannot be renewed by its holder. The URL honors\n * --api-url/config, so a local login yields a local config.\n */\nexport function buildMcpConfig(apiUrl: string) {\n return {\n mcpServers: {\n anima: {\n type: \"http\",\n url: `${apiUrl.replace(/\\/$/, \"\")}/v1/mcp`,\n },\n },\n };\n}\n","import { agentSessionFromTokenResponse, persistAgentSession, type AgentSession } from \"./agentSession.js\";\nimport { authError, CliError, EXIT_CODES } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * OAuth 2.0 Device Authorization Grant (RFC 8628) against the Anima\n * authorization server. The flow needs no browser on this machine: the server\n * returns a short human code, the human approves at the verification URL (any\n * device), and this client polls the token endpoint until the decision lands.\n *\n * The issued token is a scoped AGENT token: it acts within the workspaces and\n * capabilities the human approved on the consent screen, and the team can\n * revoke it at any time. Access tokens last 24 h and `resolveAuth` renews them\n * before they expire; running the flow again is only needed once the approval\n * itself ends (re-approval reconnects to the same agent when the same agent\n * name is kept).\n */\n\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst DEFAULT_CLIENT_NAME = \"AgentGrid CLI\";\n\nexport type DeviceVerificationInfo = {\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresInSeconds: number;\n};\n\n\ntype DeviceLoginOptions = {\n apiUrl: string;\n clientName?: string;\n /** Called once with the code the human must enter — the caller renders it. */\n onVerification: (info: DeviceVerificationInfo) => void;\n /** Injectable for tests. */\n fetchFn?: typeof fetch;\n sleepFn?: (ms: number) => Promise<void>;\n};\n\nconst defaultSleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\nexport async function loginWithDeviceFlow(options: DeviceLoginOptions): Promise<AgentSession> {\n const fetchFn = options.fetchFn ?? fetch;\n const sleep = options.sleepFn ?? defaultSleep;\n const base = options.apiUrl.replace(/\\/$/, \"\");\n\n // Step 1 — start the flow. No client registration: the server namespaces\n // device-flow agents itself; client_name is display-only on the consent page.\n const startUrl = `${base}/oauth/device_authorization`;\n logEvent(\"device_authorization_request\", { url: startUrl });\n const startResponse = await fetchFn(startUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ client_name: options.clientName ?? DEFAULT_CLIENT_NAME }).toString(),\n });\n logEvent(\"device_authorization_response\", { url: startUrl, status: startResponse.status });\n\n if (!startResponse.ok) {\n const detail = await startResponse.text().catch(() => \"\");\n logEvent(\"device_authorization_failed\", { url: startUrl, status: startResponse.status, body: detail.slice(0, 500) });\n const hint =\n startResponse.status === 404\n ? ` — no device endpoint at ${startUrl}. Check --api-url points to an API that has the device grant deployed.`\n : \"\";\n throw new CliError(\n \"API_ERROR\",\n `Device authorization failed (HTTP ${startResponse.status})${hint}`,\n EXIT_CODES.API_ERROR\n );\n }\n\n const start = (await startResponse.json()) as {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n };\n\n options.onVerification({\n userCode: start.user_code,\n verificationUri: start.verification_uri,\n verificationUriComplete: start.verification_uri_complete,\n expiresInSeconds: start.expires_in,\n });\n\n // Step 2 — poll until the human decides. The server enforces pacing:\n // slow_down means add 5 seconds to the interval (RFC 8628 §3.5).\n let intervalMs = Math.max(1, start.interval) * 1000;\n const deadline = Date.now() + start.expires_in * 1000;\n\n while (Date.now() < deadline) {\n await sleep(intervalMs);\n\n const pollResponse = await fetchFn(`${base}/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: DEVICE_GRANT_TYPE,\n device_code: start.device_code,\n }).toString(),\n });\n\n const body = (await pollResponse.json()) as Record<string, unknown>;\n logEvent(\"device_token_poll\", { status: pollResponse.status, error: body.error });\n\n if (pollResponse.ok && typeof body.access_token === \"string\") {\n const session = agentSessionFromTokenResponse(body);\n persistAgentSession(session);\n return session;\n }\n\n switch (body.error) {\n case \"authorization_pending\":\n continue;\n case \"slow_down\":\n intervalMs += 5000;\n continue;\n case \"access_denied\":\n throw authError(\"The authorization request was denied.\");\n case \"expired_token\":\n throw authError(\"The device code expired before approval. Run the login again.\");\n default:\n throw new CliError(\n \"API_ERROR\",\n `Unexpected token response: ${body.error ?? `HTTP ${pollResponse.status}`}`,\n EXIT_CODES.API_ERROR\n );\n }\n }\n\n throw authError(\"The device code expired before approval. Run the login again.\");\n}\n","import { agentSessionFromTokenResponse, persistAgentSession, type AgentSession } from \"./agentSession.js\";\nimport { CliError, EXIT_CODES } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * Invite-door redemption: exchange a pre-approved, single-use invite code for\n * a scoped agent token (`grant_type=urn:ietf:params:oauth:grant-type:\n * pre-authorized_code`) and store it exactly like the device login — so\n * `logout`, `mcp-config`, `get-git-token`, and the rest of the CLI work\n * identically for invited agents.\n *\n * The human mints the invite in-app and hands the agent a URL like\n * `https://api.agentgrid.io/invite/<code>.md`; this accepts either\n * that full URL or the bare code. A single POST returns the token directly —\n * there is no polling and no browser step (consent already happened at mint).\n */\n\nconst PRE_AUTHORIZED_GRANT = \"urn:ietf:params:oauth:grant-type:pre-authorized_code\";\n\n\nexport type ParsedInvite = {\n code: string;\n /** Origin of the invite URL, when a URL was given — the API the invite was minted on. */\n origin?: string;\n};\n\n/**\n * Accept the invite URL (`…/invite/<code>.md`), the same without `.md`, or the\n * bare code. When a URL is given, its origin is returned too: the invite was\n * minted on that host, so it is the right API base unless the caller overrides.\n */\nexport function parseInvite(input: string): ParsedInvite {\n const trimmed = input.trim();\n if (/^https?:\\/\\//i.test(trimmed)) {\n let url: URL;\n try {\n url = new URL(trimmed);\n } catch {\n throw new CliError(\"VALIDATION_ERROR\", `Not a valid invite URL: ${trimmed}`, EXIT_CODES.VALIDATION_ERROR);\n }\n const last = url.pathname.split(\"/\").filter(Boolean).pop() ?? \"\";\n const code = last.replace(/\\.md$/, \"\");\n if (!code) {\n throw new CliError(\n \"VALIDATION_ERROR\",\n \"The invite URL carries no code — expected …/invite/<code>.md\",\n EXIT_CODES.VALIDATION_ERROR\n );\n }\n return { code, origin: url.origin };\n }\n return { code: trimmed.replace(/\\.md$/, \"\") };\n}\n\ntype InviteLoginOptions = {\n apiUrl: string;\n invite: string;\n /** Injectable for tests. */\n fetchFn?: typeof fetch;\n};\n\nexport async function loginWithInvite(options: InviteLoginOptions): Promise<AgentSession> {\n const fetchFn = options.fetchFn ?? fetch;\n const { code } = parseInvite(options.invite);\n const base = options.apiUrl.replace(/\\/$/, \"\");\n\n const tokenUrl = `${base}/oauth/token`;\n logEvent(\"invite_redeem_request\", { url: tokenUrl });\n const response = await fetchFn(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: PRE_AUTHORIZED_GRANT,\n \"pre-authorized_code\": code,\n }).toString(),\n });\n\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n logEvent(\"invite_redeem_response\", { status: response.status, error: body.error });\n\n if (!response.ok || typeof body.access_token !== \"string\") {\n // The server's error_description is prompt-ware written for the agent —\n // surface it verbatim.\n const description =\n typeof body.error_description === \"string\"\n ? body.error_description\n : `Invite redemption failed (HTTP ${response.status})`;\n throw new CliError(\"AUTH_INVALID\", description, EXIT_CODES.AUTH_ERROR);\n }\n\n const session = agentSessionFromTokenResponse(body);\n persistAgentSession(session);\n\n return session;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport {\n saveCredential,\n saveFigmaToken,\n clearStorage,\n readCredentials,\n getCredentialsPath,\n extractTeamIdFromJWT,\n} from \"../auth/store.js\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { revokeStoredRefreshToken } from \"../auth/refresh.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printSuccess, printError, printKeyValue, printInfo } from \"../output/pretty.js\";\nimport { CliError } from \"../api/errors.js\";\n\nconst DEFAULT_API_URL = \"https://api.agentgrid.io\";\n\nexport const authCommand = new Command(\"auth\")\n .description(\"Manage authentication\")\n .option(\"--token <token>\", \"Store AgentGrid API token\")\n .option(\"--figma-token <token>\", \"Store Figma personal access token\")\n .option(\"--team-id <teamId>\", \"Team ID to associate with token\")\n .option(\"--status\", \"Show current auth status\")\n .option(\"--logout\", \"Clear stored credentials (alias for `anima logout`)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n\n try {\n if (opts.token || opts.figmaToken) {\n const toSave: { teamId?: string } = {};\n\n if (opts.token) {\n // A pasted token is a personal API token: full user authority, minted\n // outside any OAuth door, with nothing to renew.\n toSave.teamId = opts.teamId ?? extractTeamIdFromJWT(opts.token);\n saveCredential({ tokenType: \"account\", token: opts.token, teamId: toSave.teamId });\n }\n if (opts.figmaToken) {\n saveFigmaToken(opts.figmaToken);\n }\n\n if (mode === \"pretty\") {\n printSuccess(\"Credentials saved to \" + getCredentialsPath());\n if (opts.token) {\n printKeyValue(\"AgentGrid token\", \"saved\");\n if (toSave.teamId) printKeyValue(\"Team ID\", toSave.teamId);\n }\n if (opts.figmaToken) {\n printKeyValue(\"Figma token\", \"saved\");\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"token_saved\",\n path: getCredentialsPath(),\n ...(opts.token ? { teamId: toSave.teamId } : {}),\n ...(opts.figmaToken ? { figmaToken: true } : {}),\n });\n }\n return;\n }\n\n if (opts.logout) {\n const revoked = await revokeStoredRefreshToken(resolveApiUrl(opts.apiUrl));\n const deleted = clearStorage();\n if (mode === \"pretty\") {\n if (deleted) {\n printSuccess(\"Credentials cleared\");\n } else {\n printInfo(\"No stored credentials found\");\n }\n } else {\n outputResult(mode, { success: true, action: \"logged_out\", hadCredentials: deleted, revoked });\n }\n return;\n }\n\n if (opts.status) {\n try {\n const auth = await resolveAuth(opts.apiUrl);\n const creds = readCredentials();\n const sourceName = auth.source === \"env\" ? \"ANIMA_API_TOKEN env var\" : getCredentialsPath();\n const hasFigma = !!(process.env.FIGMA_TOKEN || creds?.figmaToken);\n if (mode === \"pretty\") {\n printSuccess(\"Token configured\");\n printKeyValue(\"Source\", sourceName);\n printKeyValue(\"AgentGrid token\", auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4));\n printKeyValue(\"Token type\", auth.tokenType === \"agent\" ? \"agent (scoped, revocable)\" : \"account (personal API token)\");\n if (creds?.tokenType === \"agent\" && creds.expiresAt) printKeyValue(\"Expires\", creds.expiresAt);\n if (auth.teamId) printKeyValue(\"Team ID\", auth.teamId);\n printKeyValue(\"Figma token\", hasFigma ? \"configured\" : \"not set (needed for codegen/f2c)\");\n } else {\n outputResult(mode, {\n success: true,\n source: auth.source,\n tokenType: auth.tokenType ?? \"account\",\n tokenPreview: auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4),\n teamId: auth.teamId,\n expiresAt: creds?.tokenType === \"agent\" ? creds.expiresAt : undefined,\n figmaToken: hasFigma,\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n } else {\n throw err;\n }\n }\n return;\n }\n\n // No flag: show help\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"Auth commands:\");\n console.log(` ${chalk.cyan(\"anima login\")} Log in (device flow — approve on any browser)`);\n console.log(` ${chalk.cyan(\"anima logout\")} Clear all credentials`);\n console.log(` ${chalk.cyan(\"anima auth --status\")} Check auth status`);\n console.log(` ${chalk.cyan(\"anima auth --figma-token <T>\")} Save Figma token (needed for codegen/f2c)`);\n console.log();\n console.log(` Figma token: ${chalk.cyan.underline(\"https://www.figma.com\")} > Settings > Personal access tokens`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n message: \"Run `anima login`, or use --status / --logout / --figma-token\",\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { clearStorage, getCredentialsPath } from \"../auth/store.js\";\nimport { revokeStoredRefreshToken } from \"../auth/refresh.js\";\nimport { deleteConfig, resolveApiUrl } from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { printSuccess, printInfo } from \"../output/pretty.js\";\n\n/**\n * `anima logout` — clear all stored credentials from this machine. Removes the\n * credentials file (Anima token, Figma token, agent metadata) and the config\n * directory, and revokes the agent credentials server-side so a copy taken from\n * this machine stops working.\n */\nexport const logoutCommand = new Command(\"logout\")\n .description(\"Clear all stored credentials (AgentGrid + Figma tokens) from this machine\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n // Revoke before clearing: this kills every credential descended from the\n // same consent, so a copy of the token taken from this machine stops\n // working too.\n const revoked = await revokeStoredRefreshToken(resolveApiUrl(opts.apiUrl));\n const hadCredentials = clearStorage();\n // Full machine reset: logout removes stored config too (e.g. the api-url\n // persisted by `login --invite`), so the machine is pristine afterwards.\n deleteConfig();\n\n if (mode === \"pretty\") {\n if (hadCredentials) {\n printSuccess(\"Logged out — all credentials cleared from \" + getCredentialsPath());\n if (revoked) printInfo(\"Agent credentials revoked server-side\");\n } else {\n printInfo(\"No stored credentials found\");\n }\n } else {\n outputResult(mode, { success: true, action: \"logged_out\", hadCredentials, revoked });\n }\n });\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printError } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError, apiError } from \"../api/errors.js\";\n\ntype UnpublishResult = {\n success: boolean;\n message?: string;\n error?: string;\n reason?: string;\n};\n\n/** Mirror of the `artifact-unpublish` MCP tool — the inverse of `publish`. */\nexport const unpublishCommand = new Command(\"unpublish\")\n .description(\"Take a published artifact offline (clears its live URL; code and artifact stay intact)\")\n .argument(\"<sessionId>\", \"Session ID of the published artifact\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (sessionId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const auth = await resolveAuth(opts.apiUrl);\n progress.start(\"Unpublishing...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<UnpublishResult>(\"artifact-unpublish\", { sessionId })\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Unpublish failed\", result);\n }\n\n progress.succeed(\"Unpublished\");\n if (mode === \"pretty\") {\n printSuccess(result.message || `Artifact ${sessionId} is no longer publicly reachable.`);\n } else {\n outputResult(mode, { success: true, sessionId, ...(result.message ? { message: result.message } : {}) });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printError } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError, apiError, validationError } from \"../api/errors.js\";\n\ntype UpdateResult = {\n success: boolean;\n message?: string;\n error?: string;\n reason?: string;\n};\n\n/**\n * Mirror of the `artifact-update_metadata` MCP tool — metadata only (name,\n * visibility); it never touches code or content (that is the git flow).\n */\nexport const updateCommand = new Command(\"update\")\n .description(\"Update an artifact's metadata: display name and/or visibility (never touches code)\")\n .argument(\"<sessionId>\", \"Session ID of the artifact\")\n .option(\"--name <name>\", \"New display name\")\n .option(\"--privacy <privacy>\", \"public (anyone with the link) | private (team only)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (sessionId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n if (!opts.name && !opts.privacy) {\n throw validationError(\"Nothing to update — pass --name and/or --privacy\");\n }\n if (opts.privacy && ![\"public\", \"private\"].includes(opts.privacy)) {\n throw validationError(`Invalid privacy \"${opts.privacy}\". Must be public or private.`);\n }\n\n const auth = await resolveAuth(opts.apiUrl);\n progress.start(\"Updating...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n client.callTool<UpdateResult>(\"artifact-update_metadata\", {\n sessionId,\n ...(opts.name ? { name: opts.name } : {}),\n ...(opts.privacy ? { privacy: opts.privacy } : {}),\n })\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Update failed\", result);\n }\n\n progress.succeed(\"Updated\");\n if (mode === \"pretty\") {\n printSuccess(result.message || `Artifact ${sessionId} updated.`);\n } else {\n outputResult(mode, { success: true, sessionId, ...(result.message ? { message: result.message } : {}) });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport {\n readConfig,\n setConfig,\n unsetConfig,\n getConfigPath,\n isConfigKey,\n configKeys,\n CONFIG_KEYS,\n resolveApiUrl,\n DEFAULT_API_URL,\n type ConfigKey,\n} from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { printSuccess, printInfo, printKeyValue } from \"../output/pretty.js\";\nimport { validationError } from \"../api/errors.js\";\n\n/**\n * `anima config` — store non-secret CLI preferences in\n * ~/.config/anima/config.json so you don't have to pass flags like `--api-url`\n * every time. Resolution precedence for the API URL: flag → ANIMA_API_URL env →\n * stored config → default.\n *\n * anima config set api-url http://localhost:3789\n * anima config get api-url\n * anima config list\n * anima config unset api-url\n */\nexport const configCommand = new Command(\"config\").description(\n `Store CLI preferences (keys: ${configKeys().join(\", \")})`\n);\n\nconfigCommand\n .command(\"set <key> <value>\")\n .description(\"Set a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, value: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n if (key === \"api-url\") assertUrl(value);\n setConfig(key, value);\n\n if (mode === \"pretty\") printSuccess(`Set ${key} = ${value}`);\n else outputResult(mode, { success: true, action: \"config_set\", key, value });\n });\n\nconfigCommand\n .command(\"get <key>\")\n .description(\"Print a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const value = readConfig()[CONFIG_KEYS[key]];\n\n if (mode === \"pretty\") {\n if (value) console.log(value);\n else printInfo(`${key} is not set`);\n } else {\n outputResult(mode, { success: true, key, value: value ?? null });\n }\n });\n\nconfigCommand\n .command(\"list\")\n .alias(\"ls\")\n .description(\"Show all config values and where the API URL resolves from\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const mode = detectOutputMode(opts);\n const config = readConfig();\n const resolvedApiUrl = resolveApiUrl();\n\n if (mode === \"pretty\") {\n printInfo(\"Config: \" + getConfigPath());\n printKeyValue(\"api-url\", config.apiUrl ?? `(default) ${DEFAULT_API_URL}`);\n if (process.env.ANIMA_API_URL) {\n printInfo(`ANIMA_API_URL env is set — it overrides config (effective: ${resolvedApiUrl})`);\n }\n } else {\n outputResult(mode, {\n success: true,\n path: getConfigPath(),\n config,\n resolved: { apiUrl: resolvedApiUrl },\n });\n }\n });\n\nconfigCommand\n .command(\"unset <key>\")\n .description(\"Remove a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const removed = unsetConfig(key);\n\n if (mode === \"pretty\") {\n if (removed) printSuccess(`Unset ${key}`);\n else printInfo(`${key} was not set`);\n } else {\n outputResult(mode, { success: true, action: \"config_unset\", key, removed });\n }\n });\n\nfunction assertKey(key: string): asserts key is ConfigKey {\n if (!isConfigKey(key)) {\n throw validationError(`Unknown config key \"${key}\". Valid keys: ${configKeys().join(\", \")}`);\n }\n}\n\nfunction assertUrl(value: string): void {\n try {\n new URL(value);\n } catch {\n throw validationError(`\"${value}\" is not a valid URL`);\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputError, outputResult } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printError, printKeyValue, printSuccess } from \"../output/pretty.js\";\nimport { parsePlaygroundUrl } from \"../utils/playgroundUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError, validationError } from \"../api/errors.js\";\n\ntype DuplicateSuccess = {\n success: true;\n sessionId: string;\n sourceSessionId: string;\n name: string;\n playgroundUrl: string;\n previewUrl: string;\n nextSteps: string;\n};\n\ntype DuplicateFailure = {\n success: false;\n code?: string;\n error?: string;\n reason?: string;\n};\n\ntype DuplicateResult = DuplicateSuccess | DuplicateFailure;\n\n/** Exact input accepted by the artifact-duplicate MCP tool. */\nexport function buildDuplicateArgs(\n artifactUrl: string,\n name?: string\n): { sessionId: string; name?: string } {\n const sessionId = parsePlaygroundUrl(artifactUrl);\n if (!sessionId) {\n throw validationError(\"A source artifact URL or session ID is required\");\n }\n if (name !== undefined && (name.length === 0 || name.length > 120)) {\n throw validationError(\"--name must be between 1 and 120 characters\");\n }\n return { sessionId, ...(name !== undefined ? { name } : {}) };\n}\n\nexport function createDuplicateCommand(): Command {\n return new Command(\"duplicate\")\n .description(\n \"Duplicate an artifact into a new, independent artifact. Copies code, assets, and supported database content; chat and custom domains are not copied. Duplication is non-idempotent: if a request times out or its response is lost, list recent artifacts before retrying because the first request may already have created the copy.\"\n )\n .argument(\"<artifactUrl>\", \"Source artifact URL or session ID\")\n .option(\"--name <name>\", \"Display name for the duplicate (defaults to '<source name> (Copy)')\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const args = buildDuplicateArgs(artifactUrl, opts.name);\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(\"Duplicating artifact...\");\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<DuplicateResult>(\"artifact-duplicate\", args)\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Artifact duplication failed\", result);\n }\n\n progress.succeed(\"Artifact duplicated\");\n if (mode === \"pretty\") {\n console.log();\n printSuccess(\"Artifact duplicated successfully!\");\n printKeyValue(\"Name\", result.name);\n printKeyValue(\"Session ID\", result.sessionId);\n printKeyValue(\"Source session\", result.sourceSessionId);\n printKeyValue(\"Artifact\", chalk.cyan.underline(result.playgroundUrl));\n printKeyValue(\"Preview\", chalk.cyan.underline(result.previewUrl));\n printKeyValue(\"Next steps\", result.nextSteps);\n console.log();\n } else {\n outputResult(mode, result);\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n}\n\nexport const duplicateCommand = createDuplicateCommand();\n"],"mappings":"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","names":["Command","chalk","required","fs","path","fs","path","os","CONFIG_DIR","path","chalk","Command","chalk","Command","chalk","relative","Command","Command","Command","fs","path","Command","Command","chalk","Command","chalk","Command","Command","chalk","Command","apiUrl","chalk","Command","Command","chalk","DEFAULT_API_URL","Command","chalk","Command","Command","Command","Command","Command","Command","Command","Command","Command","chalk","Command","chalk","Command"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/auth/store.ts","../src/auth/jwt.ts","../src/api/errors.ts","../src/auth/agentSession.ts","../src/output/log.ts","../src/auth/refresh.ts","../src/config/store.ts","../src/auth/token.ts","../src/api/mcp.ts","../src/version.ts","../src/output/formatter.ts","../src/output/progress.ts","../src/output/pretty.ts","../src/utils/figma.ts","../src/utils/projectSource.ts","../src/utils/playgroundUrl.ts","../src/api/anonymousCreate.ts","../src/commands/list.ts","../src/commands/publish.ts","../src/commands/codegen.ts","../src/utils/files.ts","../src/commands/getGitToken.ts","../src/utils/gitToken.ts","../src/commands/mcpConfig.ts","../src/commands/login.ts","../src/auth/device.ts","../src/auth/invite.ts","../src/auth/handoff.ts","../src/commands/auth.ts","../src/commands/logout.ts","../src/commands/unpublish.ts","../src/commands/update.ts","../src/commands/config.ts","../src/commands/duplicate.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createCommand } from \"./commands/create.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { publishCommand } from \"./commands/publish.js\";\nimport { codegenCommand } from \"./commands/codegen.js\";\nimport { getGitTokenCommand } from \"./commands/getGitToken.js\";\nimport { mcpConfigCommand } from \"./commands/mcpConfig.js\";\nimport { authCommand } from \"./commands/auth.js\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { logoutCommand } from \"./commands/logout.js\";\nimport { unpublishCommand } from \"./commands/unpublish.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { configCommand } from \"./commands/config.js\";\nimport { duplicateCommand } from \"./commands/duplicate.js\";\nimport { CliError } from \"./api/errors.js\";\n\n// Version comes from package.json so `--version` always matches the published\n// build (shared with the MCP clientInfo).\nimport { version } from \"./version.js\";\n\nconst program = new Command()\n .name(\"anima\")\n .description(\n `AgentGrid CLI — host, edit, and publish your work on AgentGrid. Every artifact is a\nreal git repository; each command runs an AgentGrid tool for you.\n\nTHE MAIN FLOW (build something and put it on AgentGrid):\n 1. npx @animaapp/cli login # once; a human approves\n 2. npx @animaapp/cli create -t import --from ./my-project # your code → a live app\n (or: create -t empty --framework html — an empty repo you push to)\n 3. The response includes a rw gitRemoteUrl — git clone, edit, commit, push:\n every push updates the live artifact.\n 4. Share the playgroundUrl with your human. That IS sharing — the artifact\n is visible at its URL. Do NOT run publish unless the human explicitly\n asked for a public site; offer it as a follow-up question instead.\n\nAUTHENTICATION:\n npx @animaapp/cli login # device flow — a human approves on any device\n npx @animaapp/cli login --invite <url> # redeem a pre-approved invite link (no approval step)\n Credentials live in ~/.config/anima/; logout removes everything.\n\nTIMING (important for AI agents):\n create -t empty|import → seconds\n create -t p2c|l2c|f2c → 3-7 minutes AI generation (keep the default 600000ms timeout)\n publish/unpublish → 1-3 minutes\n duplicate / get-git-token / update → seconds\n\nCOMMANDS:\n login Connect (device flow, or --invite to redeem an invite link)\n logout Full local reset — clears credentials and CLI config\n list List your team's artifacts (most-recently-updated first) to resume work\n create Make an artifact: import your code, empty repo, or AI-generated (p2c/l2c/f2c)\n duplicate Copy an artifact into a new, independent artifact\n get-git-token Fresh git access to an existing artifact (or after token expiry)\n update Rename an artifact or set visibility public/private (metadata only)\n publish Deploy to a public live URL — ONLY when the human asked for it\n unpublish Take a published artifact offline (inverse of publish)\n mcp-config Print an MCP server config from stored credentials (no new login)\n codegen Convert Figma design to local code files (no artifact)\n config Store CLI preferences (e.g. a default API URL)\n auth Inspect or manage credentials (status / figma token)\n\nEXAMPLES (headless flow):\n npx @animaapp/cli login --invite https://api.agentgrid.io/invite/<code>.md\n npx @animaapp/cli create -t import --from ./my-project\n npx @animaapp/cli create -t empty --framework react --name \"My app\"\n npx @animaapp/cli duplicate <artifactUrl> --name \"My copy\"\n npx @animaapp/cli get-git-token <sessionId>\n npx @animaapp/cli update <sessionId> --privacy public\n npx @animaapp/cli publish <sessionId> # only on explicit request\n npx @animaapp/cli unpublish <sessionId>\n\nOUTPUT: JSON to stdout when piped (for AI tools), pretty text in terminals.\n Progress is streamed to stderr via --verbose when in JSON mode.`\n )\n .version(version, \"-v, --version\");\n\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\nprogram.addCommand(listCommand);\nprogram.addCommand(createCommand);\nprogram.addCommand(duplicateCommand);\nprogram.addCommand(publishCommand);\nprogram.addCommand(unpublishCommand);\nprogram.addCommand(updateCommand);\nprogram.addCommand(codegenCommand);\nprogram.addCommand(getGitTokenCommand);\nprogram.addCommand(mcpConfigCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(authCommand);\n\nprogram.parseAsync(process.argv).catch((err) => {\n if (err instanceof CliError) {\n if (process.stdout.isTTY) {\n console.error(err.message);\n } else {\n process.stdout.write(\n JSON.stringify({\n success: false,\n error: { code: err.code, message: err.message },\n }) + \"\\n\"\n );\n }\n process.exit(err.exitCode);\n }\n\n console.error(err);\n process.exit(1);\n});\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSessionResult } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { collectProjectSource } from \"../utils/projectSource.js\";\nimport { PLAYGROUND_BASE } from \"../utils/playgroundUrl.js\";\nimport { createAnonymousArtifact, getAnonymousZipUploadUrl } from \"../api/anonymousCreate.js\";\nimport {\n savePendingHandoff,\n readPendingHandoff,\n clearPendingHandoff,\n getHandoffPath,\n type PendingHandoff,\n} from \"../auth/store.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { CreateType } from \"../api/types.js\";\n\n\ntype CreateResult = {\n success: boolean;\n sessionId?: string;\n playgroundUrl?: string;\n // Minted with the artifact, same shape as artifact-get_git_token.\n gitRemoteUrl?: string;\n access?: \"ro\" | \"rw\";\n expiresAt?: string;\n // Own-code only\n framework?: \"html\" | \"react\";\n artifactType?: \"app\" | \"markdown\" | \"asset\";\n fileCount?: number;\n skippedFiles?: string[];\n notes?: string;\n nextSteps?: string;\n error?: string;\n reason?: string;\n};\n\ntype ZipUploadGrant = {\n success: boolean;\n zipUploadId?: string;\n uploadUrl?: string;\n uploadUrlExpiresAt?: string;\n nextSteps?: string | string[];\n error?: string;\n reason?: string;\n};\n\nexport const createCommand = new Command(\"create\")\n .description(\n \"Create an artifact from your own code: empty for code you'll push (instant) or import your existing code (instant). Also supports AI generation: p2c/l2c/f2c (3-7 min).\"\n )\n .requiredOption(\n \"-t, --type <type>\",\n \"empty (empty repo you push to), import (create FROM your code — use --from), or AI-generated: p2c, l2c, f2c\"\n )\n .option(\"-p, --prompt <prompt>\", \"Text prompt (p2c)\")\n .option(\"-u, --url <url>\", \"Website URL (l2c)\")\n .option(\"--file-key <key>\", \"Figma file key or URL (f2c)\")\n .option(\"--nodes <nodes>\", \"Figma node IDs, comma-separated (f2c)\")\n .option(\"--figma-token <token>\", \"Figma personal access token (f2c)\")\n .option(\n \"--framework <fw>\",\n \"html | react — the only supported frameworks. REQUIRED for empty (declare react if you will push React code); detected from package.json for import\"\n )\n .option(\"--styling <style>\", \"tailwind | css | plain_css | css_modules | inline_styles\", \"tailwind\")\n .option(\"--language <lang>\", \"typescript | javascript\")\n .option(\"--ui-library <lib>\", \"mui | antd | shadcn | clean_react\")\n .option(\"--guidelines <text>\", \"Additional constraints (p2c only)\")\n .option(\n \"--artifact-type <kind>\",\n \"app | markdown \\u2014 what the artifact IS. app (default) needs an index.html; markdown needs .md files\"\n )\n .option(\"--name <name>\", \"Project name (empty/import only)\")\n .option(\"--from <path>\", \"Folder or .zip with your project (import only) — becomes the first commit\")\n .option(\n \"--anonymous\",\n \"Create without an account (import only). Returns a claim link to send a human, and a handoff token to log in with once they claim it\"\n )\n .option(\n \"--handoff <token>\",\n \"Add this artifact to an existing claim (--anonymous only), so one claim link covers them all. Defaults to the token from your last anonymous create\"\n )\n .option(\"--client-name <name>\", \"How this CLI is credited as the creator of an anonymous artifact\", \"AgentGrid CLI\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const type = opts.type as CreateType;\n validateCreateOptions(type, opts);\n\n // The anonymous fast track has no credential to resolve, so it forks\n // before auth: MCP tool calls all carry a bearer token, and the point of\n // this path is that there is not one yet. Everything below goes through\n // MCP with the stored agent token.\n if (opts.anonymous) {\n await runAnonymousCreate(opts, mode, progress);\n return;\n }\n\n const auth = await resolveAuth(opts.apiUrl);\n const figmaToken = type === \"f2c\" ? resolveFigmaToken(opts, auth.figmaToken) : undefined;\n const args = buildCreateArgs(type, opts);\n const mcpConfig = { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId, figmaToken };\n\n // Import: attach the local project. Small text-only projects go inline;\n // anything with binaries or over the inline caps is zipped and uploaded\n // via a presigned URL first (artifact-get_zip_upload_url).\n if (type === \"import\") {\n progress.start(\"Collecting project files...\");\n const source = collectProjectSource(opts.from);\n if (source.kind === \"files\") {\n args.files = source.files;\n } else {\n progress.update(`Uploading project zip (${source.reason})...`);\n const grant = await withMcp(mcpConfig, (client) =>\n client.callTool<ZipUploadGrant>(\"artifact-get_zip_upload_url\", {})\n );\n if (!grant.success || !grant.uploadUrl || !grant.zipUploadId) {\n const message = grant.reason || grant.error || \"Could not get a zip upload URL\";\n throw apiError(grant.nextSteps ? `${message}\\n${grant.nextSteps}` : message, grant);\n }\n const putResponse = await fetch(grant.uploadUrl, {\n method: \"PUT\",\n body: new Uint8Array(source.buffer),\n });\n if (!putResponse.ok) {\n throw apiError(`Zip upload failed: HTTP ${putResponse.status}`, { status: putResponse.status });\n }\n args.zipUploadId = grant.zipUploadId;\n }\n }\n\n progress.start(\n type === \"empty\"\n ? \"Creating empty artifact...\"\n : type === \"import\"\n ? \"Importing your project...\"\n : `Creating ${type.toUpperCase()} artifact...`\n );\n\n const result = await withMcp(mcpConfig, (client) =>\n client.callTool<CreateResult>(\"artifact-create\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.sessionId) {\n const message = result.reason || result.error || \"Generation failed\";\n // Own-code failures carry recovery guidance (e.g. the upload_not_found\n // duplicate-artifact warning) — losing it at the CLI boundary would\n // strip exactly what the caller needs to retry correctly.\n throw apiError(result.nextSteps ? `${message}\\n${result.nextSteps}` : message, result);\n }\n\n const playgroundUrl = result.playgroundUrl || `${PLAYGROUND_BASE}/${result.sessionId}`;\n\n progress.succeed(\"Artifact created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({ sessionId: result.sessionId, playgroundUrl });\n if (result.gitRemoteUrl) {\n console.log(` ${chalk.cyan(`git clone ${result.gitRemoteUrl}`)}`);\n console.log();\n console.log(\" Commit and push to update the live artifact.\");\n if (result.expiresAt) {\n console.log(\n ` The URL embeds a token that expires at ${result.expiresAt} and cannot be renewed;\\n` +\n ` run ${chalk.cyan(`anima get-git-token ${result.sessionId}`)} and ` +\n `${chalk.cyan(\"git remote set-url origin <new url>\")} to keep pushing.`\n );\n }\n console.log(\" Treat the URL as a secret — it grants access to this artifact.\");\n console.log();\n } else if (type === \"empty\") {\n console.log(\n ` Next: anima get-git-token ${result.sessionId} — then git clone, add your code, and git push.`\n );\n console.log();\n }\n if (type === \"import\" && result.fileCount !== undefined) {\n console.log(` ${result.fileCount} files committed (framework: ${result.framework ?? \"detected server-side\"}).`);\n if (result.skippedFiles?.length) {\n console.log(` Skipped (blocked/hidden): ${result.skippedFiles.join(\", \")}`);\n }\n if (result.notes) {\n console.log(` Note: ${result.notes}`);\n }\n console.log();\n }\n } else {\n outputResult(mode, {\n success: true,\n sessionId: result.sessionId,\n playgroundUrl,\n ...(result.gitRemoteUrl\n ? { gitRemoteUrl: result.gitRemoteUrl, access: result.access, expiresAt: result.expiresAt }\n : {}),\n ...(result.framework ? { framework: result.framework } : {}),\n ...(result.fileCount !== undefined ? { fileCount: result.fileCount } : {}),\n ...(result.skippedFiles?.length ? { skippedFiles: result.skippedFiles } : {}),\n ...(result.notes ? { notes: result.notes } : {}),\n ...(result.nextSteps ? { nextSteps: result.nextSteps } : {}),\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\n/**\n * Create an artifact with no account, then leave the handoff token where\n * `anima login --handoff` will find it. The two commands together are the whole\n * fast track — no token ever has to cross a shell argument.\n */\nasync function runAnonymousCreate(\n opts: Record<string, string>,\n mode: ReturnType<typeof detectOutputMode>,\n progress: ProgressReporter\n): Promise<void> {\n const apiUrl = resolveApiUrl(opts.apiUrl);\n\n progress.start(\"Collecting project files...\");\n const source = collectProjectSource(opts.from);\n\n let files: Record<string, string> | undefined;\n let zipUploadId: string | undefined;\n if (source.kind === \"files\") {\n files = source.files;\n } else {\n progress.update(`Uploading project zip (${source.reason})...`);\n const grant = await getAnonymousZipUploadUrl(apiUrl);\n const putResponse = await fetch(grant.uploadUrl, {\n method: \"PUT\",\n body: new Uint8Array(source.buffer),\n });\n if (!putResponse.ok) {\n throw apiError(`Zip upload failed: HTTP ${putResponse.status}`, { status: putResponse.status });\n }\n zipUploadId = grant.zipUploadId;\n }\n\n progress.start(\"Creating anonymous artifact...\");\n const request = {\n apiUrl,\n files,\n zipUploadId,\n ...(opts.framework && opts.artifactType !== \"markdown\" ? { framework: opts.framework } : {}),\n ...(opts.artifactType ? { artifactType: opts.artifactType } : {}),\n ...(opts.name ? { name: opts.name } : {}),\n clientName: opts.clientName,\n };\n\n // Reuse a handoff token so a second create joins the same claim: one link for\n // the human, one login for us, however many artifacts. An explicit token wins\n // over the stored one. A token past its deadline is already dead, and the\n // server rejects a create carrying a dead one WITHOUT creating anything — so\n // a stale stored token must never be allowed to block a fresh create.\n const reusable = opts.handoff ? { handoffToken: opts.handoff } : livePendingHandoff();\n const result = reusable\n ? await createAnonymousArtifact({ ...request, handoffToken: reusable.handoffToken }).catch((err) => {\n // The deadline is not the only way a token dies: it may have been\n // claimed and redeemed already. That is only visible from the server,\n // so fall back to starting a fresh bucket rather than failing.\n if (!isHandoffTokenInvalid(err)) throw err;\n clearPendingHandoff();\n progress.update(\"Previous claim is no longer open — starting a new one...\");\n return createAnonymousArtifact(request);\n })\n : await createAnonymousArtifact(request);\n\n const artifactUrl = result.artifactUrl;\n savePendingHandoff({\n handoffToken: result.handoffToken,\n sessionId: result.sessionId,\n artifactUrl,\n claimableUntil: result.claimableUntil,\n apiUrl,\n });\n\n progress.succeed(\"Artifact created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({ sessionId: result.sessionId });\n console.log(\" Send your human this link to claim it:\");\n console.log(` ${chalk.cyan.underline(artifactUrl)}`);\n console.log();\n console.log(` Claimable until ${result.claimableUntil}. Until then the artifact is read-only.`);\n console.log(` Then run ${chalk.cyan(\"anima login --handoff\")} to pick up your credentials.`);\n if (result.notes) console.log(` Note: ${result.notes}`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId: result.sessionId,\n artifactUrl,\n claimableUntil: result.claimableUntil,\n // Returned, not just stored: it is delivered exactly once and can never\n // be re-fetched, so a caller whose config does not outlive the process\n // would otherwise lose the only route to a credential.\n handoffToken: result.handoffToken,\n handoffStored: getHandoffPath(),\n ...(result.fileCount !== undefined ? { fileCount: result.fileCount } : {}),\n ...(result.skippedFiles?.length ? { skippedFiles: result.skippedFiles } : {}),\n ...(result.notes ? { notes: result.notes } : {}),\n nextSteps:\n `Send artifactUrl to your human — that is the artifact's page, and the link that transfers it to them. ` +\n `handoffToken is yours, never theirs: use it to log in (\\`anima login --handoff\\`, which waits until ` +\n `they claim and then stores your credentials), or to add more artifacts to the same claim ` +\n `(\\`anima create --anonymous --handoff <token>\\`). Run the login in the background if you have other work.`,\n });\n }\n}\n\n/** The stored handoff, or null once its claim window has passed. */\nfunction livePendingHandoff(): PendingHandoff | null {\n const pending = readPendingHandoff();\n if (!pending) return null;\n return new Date(pending.claimableUntil).getTime() > Date.now() ? pending : null;\n}\n\n/** The one create failure that a retry without the handoff token can fix. */\nfunction isHandoffTokenInvalid(err: unknown): boolean {\n return err instanceof CliError && /handoff_token_invalid/.test(JSON.stringify(err.detail ?? \"\"));\n}\n\nfunction validateCreateOptions(type: CreateType, opts: Record<string, string>): void {\n if (![\"empty\", \"import\", \"p2c\", \"l2c\", \"f2c\"].includes(type)) {\n throw validationError(`Invalid type \"${type}\". Must be empty, import, p2c, l2c, or f2c.`);\n }\n if (type === \"p2c\" && !opts.prompt) {\n throw validationError(\"--prompt is required for p2c type\");\n }\n if (type === \"l2c\" && !opts.url) {\n throw validationError(\"--url is required for l2c type\");\n }\n if (type === \"f2c\" && !opts.fileKey) {\n throw validationError(\"--file-key is required for f2c type\");\n }\n if (type === \"empty\" && !opts.framework && opts.artifactType !== \"markdown\") {\n throw validationError(\n \"--framework is required for type empty — html for plain HTML/CSS/JS, react for React (declare react if you will push React code)\"\n );\n }\n if (opts.artifactType && ![\"app\", \"markdown\"].includes(opts.artifactType)) {\n throw validationError(\n `Invalid --artifact-type \"${opts.artifactType}\". Must be app or markdown.`\n );\n }\n if (opts.handoff && !opts.anonymous) {\n throw validationError(\n \"--handoff only applies to --anonymous creates — it adds the new artifact to an existing claim. \" +\n \"An authenticated create already belongs to your team.\"\n );\n }\n if (opts.anonymous && type !== \"import\") {\n throw validationError(\n `--anonymous only works with -t import (got \"${type}\"). Anonymous artifacts are created FROM code you ` +\n \"already have: there is no way to push to an empty one, and AI generation needs an account.\\n\" +\n \"Log in first for the other types: anima login\"\n );\n }\n if (type === \"import\" && !opts.from) {\n throw validationError(\"--from <folder|zip> is required for type import — the path to the project to import\");\n }\n if (type !== \"import\" && opts.from) {\n throw validationError(\"--from is only valid with -t import\");\n }\n}\n\nfunction resolveFigmaToken(opts: Record<string, string>, stored?: string): string {\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || stored;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required for f2c. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n return figmaToken;\n}\n\nfunction buildCreateArgs(type: CreateType, opts: Record<string, string>): Record<string, unknown> {\n // empty: framework is required (validated above) — the caller declares what\n // they'll push. import: framework only when explicit — the server detects\n // it from package.json otherwise. The files/zipUploadId for import are\n // attached later by the action (they may need the upload leg first).\n if (type === \"empty\" || type === \"import\") {\n return {\n type,\n // A document has no framework to build with, and declaring one on an\n // import is what made markdown artifacts render as empty apps.\n ...(opts.framework && opts.artifactType !== \"markdown\" ? { framework: opts.framework } : {}),\n ...(opts.artifactType ? { artifactType: opts.artifactType } : {}),\n ...(opts.name ? { name: opts.name } : {}),\n };\n }\n\n // Generation types: html is the default — aligned with the MCP\n // artifact-create surface. Only html and react are supported.\n const framework = opts.framework ?? \"html\";\n // Default language to typescript when framework is react (matches the web import form).\n const language = opts.language ?? (framework === \"react\" ? \"typescript\" : undefined);\n\n const artifactType = opts.artifactType;\n const args: Record<string, unknown> = {\n type,\n // framework describes how to build an app; a document has none.\n ...(artifactType === \"markdown\" ? {} : { framework }),\n ...(artifactType ? { artifactType } : {}),\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n switch (type) {\n case \"p2c\":\n args.prompt = opts.prompt;\n if (opts.guidelines) args.guidelines = opts.guidelines;\n break;\n case \"l2c\":\n args.url = opts.url;\n break;\n case \"f2c\": {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n args.fileKey = fileKey;\n args.nodesId = nodesId;\n break;\n }\n }\n\n return args;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".config\", \"anima\");\nconst CREDENTIALS_FILE = path.join(CONFIG_DIR, \"credentials.json\");\nconst HANDOFF_FILE = path.join(CONFIG_DIR, \"handoff.json\");\n\n/**\n * A scoped, revocable identity from one of the OAuth doors. Every field is\n * present — agentSession.ts refuses a partial one — so an agent credential that\n * cannot renew itself is not representable.\n */\nexport type AgentCredential = {\n tokenType: \"agent\";\n token: string;\n teamId: string;\n agentId: string;\n expiresAt: string; // ISO — when `token` stops being accepted\n // Single use — see refresh.ts. Exchanged for a new pair at expiry.\n refreshToken: string;\n refreshExpiresAt: string; // ISO — the refresh token's own idle deadline\n};\n\n/**\n * A personal API token pasted in with `anima auth --token`. It carries the\n * user's full authority rather than a consented scope, is minted outside any\n * OAuth door, and has nothing to renew. Named `account` to match how the API\n * classifies the same credential (`TokenClass` in public-shared).\n */\nexport type AccountCredential = {\n tokenType: \"account\";\n token: string;\n teamId?: string;\n};\n\n/** Not an Anima credential — it accompanies either kind, or stands alone. */\ntype FigmaCredential = { figmaToken?: string };\n\nexport type Credentials = FigmaCredential & (AgentCredential | AccountCredential);\n\n/**\n * What the credential file holds, narrowed. `absent` and `malformed` are kept\n * apart for the same reason the backend's `classifyToken` separates `unknown`\n * from `malformed`: \"you have never logged in\" and \"your credential file is\n * damaged\" deserve different answers.\n */\nexport type StoredCredentials =\n | { kind: \"agent\"; credential: AgentCredential; figmaToken?: string }\n | { kind: \"account\"; credential: AccountCredential; figmaToken?: string }\n | { kind: \"figma-only\"; figmaToken: string }\n | { kind: \"absent\" }\n | { kind: \"malformed\" };\n\n/** Read and narrow. The single place that decides what the file on disk is. */\nexport function classifyCredentials(): StoredCredentials {\n let parsed: Record<string, unknown>;\n try {\n if (!fs.existsSync(CREDENTIALS_FILE)) return { kind: \"absent\" };\n parsed = JSON.parse(fs.readFileSync(CREDENTIALS_FILE, \"utf-8\"));\n } catch {\n return { kind: \"malformed\" };\n }\n\n const figmaToken = typeof parsed.figmaToken === \"string\" ? parsed.figmaToken : undefined;\n if (typeof parsed.token !== \"string\") {\n return figmaToken ? { kind: \"figma-only\", figmaToken } : { kind: \"absent\" };\n }\n\n // An agent credential is only usable if it carries everything renewal needs;\n // anything short of that is damaged rather than a different kind.\n if (parsed.tokenType === \"agent\") {\n const required = [\"teamId\", \"agentId\", \"expiresAt\", \"refreshToken\", \"refreshExpiresAt\"] as const;\n if (required.some((field) => typeof parsed[field] !== \"string\")) {\n return { kind: \"malformed\" };\n }\n return { kind: \"agent\", credential: parsed as unknown as AgentCredential, figmaToken };\n }\n\n return {\n kind: \"account\",\n credential: {\n tokenType: \"account\",\n token: parsed.token,\n teamId: typeof parsed.teamId === \"string\" ? parsed.teamId : undefined,\n },\n figmaToken,\n };\n}\n\n/** Convenience over `classifyCredentials` for callers that only need the credential. */\nexport function readCredentials(): Credentials | null {\n const stored = classifyCredentials();\n if (stored.kind !== \"agent\" && stored.kind !== \"account\") return null;\n return { ...stored.credential, ...(stored.figmaToken ? { figmaToken: stored.figmaToken } : {}) };\n}\n\n/** Replace the Anima credential, keeping the Figma token that may sit beside it. */\nexport function saveCredential(credential: AgentCredential | AccountCredential): void {\n const figmaToken = readCredentials()?.figmaToken;\n write({ ...credential, ...(figmaToken ? { figmaToken } : {}) });\n}\n\n/** The Figma token accompanies either credential kind, so it merges on its own. */\nexport function saveFigmaToken(figmaToken: string): void {\n const existing = readCredentials();\n write({ ...(existing ?? {}), figmaToken } as Credentials);\n}\n\nfunction write(credentials: Credentials): void {\n writeSecretJson(CREDENTIALS_FILE, { ...credentials });\n}\n\nfunction writeSecretJson(file: string, data: Record<string, unknown>): void {\n const merged = { ...data };\n for (const key of Object.keys(merged)) {\n if (merged[key] === undefined) delete merged[key];\n }\n\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n // Write to a sibling temp file and rename: a crash mid-write must not leave a\n // truncated file, because losing the refresh token means a full re-login.\n const tmp = `${file}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + \"\\n\", { mode: 0o600 });\n fs.renameSync(tmp, file);\n}\n\nexport function deleteCredentials(): boolean {\n try {\n if (fs.existsSync(CREDENTIALS_FILE)) {\n fs.unlinkSync(CREDENTIALS_FILE);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * An anonymous create hands back a handoff token: not yet an identity, but the\n * one secret that can become one once a human claims the artifact. Kept beside\n * the credentials — same directory, same 0600, same clearing on logout — so\n * `anima login --handoff` needs no argument and the token never has to travel\n * through a shell argv, where `ps` would expose it.\n *\n * `apiUrl` is part of the record because a handoff token is only redeemable on\n * the origin that minted it.\n */\nexport type PendingHandoff = {\n handoffToken: string;\n sessionId: string;\n artifactUrl: string;\n /** ISO — the latest deadline in the bucket; polling past it cannot succeed. */\n claimableUntil: string;\n apiUrl: string;\n};\n\nexport function savePendingHandoff(pending: PendingHandoff): void {\n writeSecretJson(HANDOFF_FILE, { ...pending });\n}\n\n/** Null when absent, unreadable, or missing a field the poll would need. */\nexport function readPendingHandoff(): PendingHandoff | null {\n try {\n if (!fs.existsSync(HANDOFF_FILE)) return null;\n const parsed = JSON.parse(fs.readFileSync(HANDOFF_FILE, \"utf-8\"));\n const required = [\"handoffToken\", \"sessionId\", \"artifactUrl\", \"claimableUntil\", \"apiUrl\"] as const;\n if (required.some((field) => typeof parsed[field] !== \"string\")) return null;\n return parsed as PendingHandoff;\n } catch {\n return null;\n }\n}\n\nexport function clearPendingHandoff(): boolean {\n try {\n if (!fs.existsSync(HANDOFF_FILE)) return false;\n fs.unlinkSync(HANDOFF_FILE);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function getHandoffPath(): string {\n return HANDOFF_FILE;\n}\n\n/**\n * Full logout: remove every stored token (all live in credentials.json) and\n * the config directory itself when nothing else is left in it. Returns whether\n * any credentials were present.\n */\nexport function clearStorage(): boolean {\n const had = deleteCredentials();\n // A pending handoff is a live secret too — logging out must not leave one\n // behind for the next `login --handoff` to silently pick up.\n clearPendingHandoff();\n try {\n if (fs.existsSync(CONFIG_DIR) && fs.readdirSync(CONFIG_DIR).length === 0) {\n fs.rmdirSync(CONFIG_DIR);\n }\n } catch {\n /* leaving an empty dir behind is harmless */\n }\n return had;\n}\n\nexport function getCredentialsPath(): string {\n return CREDENTIALS_FILE;\n}\n\n/**\n * Extract the defaultTeamId from a JWT token payload (base64-decoded, no verification).\n * Returns undefined if extraction fails.\n */\nexport function extractTeamIdFromJWT(token: string): string | undefined {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf-8\")\n );\n return payload.defaultTeamId ?? undefined;\n } catch {\n return undefined;\n }\n}\n","/** Decode a JWT payload without verification (display/bookkeeping only). */\nexport function decodeJwtPayload(token: string): Record<string, unknown> | undefined {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n return JSON.parse(Buffer.from(parts[1], \"base64url\").toString(\"utf-8\"));\n } catch {\n return undefined;\n }\n}\n","export const EXIT_CODES = {\n SUCCESS: 0,\n API_ERROR: 1,\n AUTH_ERROR: 2,\n VALIDATION_ERROR: 3,\n TIMEOUT: 4,\n} as const;\n\nexport type ErrorCode =\n | \"AUTH_REQUIRED\"\n | \"AUTH_INVALID\"\n | \"VALIDATION_ERROR\"\n | \"API_ERROR\"\n | \"TIMEOUT\"\n | \"CONNECTION_ERROR\";\n\nexport class CliError extends Error {\n code: ErrorCode;\n exitCode: number;\n detail?: unknown;\n\n constructor(\n code: ErrorCode,\n message: string,\n exitCode: number,\n detail?: unknown\n ) {\n super(message);\n this.name = \"CliError\";\n this.code = code;\n this.exitCode = exitCode;\n this.detail = detail;\n }\n}\n\nexport function authError(message: string): CliError {\n return new CliError(\"AUTH_REQUIRED\", message, EXIT_CODES.AUTH_ERROR);\n}\n\nexport function validationError(message: string, detail?: unknown): CliError {\n return new CliError(\n \"VALIDATION_ERROR\",\n message,\n EXIT_CODES.VALIDATION_ERROR,\n detail\n );\n}\n\nexport function apiError(message: string, detail?: unknown): CliError {\n return new CliError(\"API_ERROR\", message, EXIT_CODES.API_ERROR, detail);\n}\n\nexport function timeoutError(): CliError {\n return new CliError(\n \"TIMEOUT\",\n \"Request timed out. Generation can take 3-7 minutes. Try increasing --timeout.\",\n EXIT_CODES.TIMEOUT\n );\n}\n","import { decodeJwtPayload } from \"./jwt.js\";\nimport { saveCredential } from \"./store.js\";\nimport { authError } from \"../api/errors.js\";\n\n/**\n * What a door hands back once a human has approved. Every field is required:\n * the token endpoint mints them together, so a missing one means the server is\n * not the one this CLI targets — better caught at login than a day later, when\n * renewal silently does not happen.\n */\nexport type AgentSession = {\n token: string;\n teamId: string;\n agentId: string;\n expiresAt: string;\n refreshToken: string;\n refreshExpiresAt: string;\n};\n\nfunction required<T>(value: T | undefined, field: string): T {\n if (value === undefined) {\n throw authError(\n `The server's token response is missing \\`${field}\\`. Check --api-url points at an Anima API that issues agent credentials.`\n );\n }\n return value;\n}\n\n/**\n * Build a session from a token-endpoint response, or fail naming what was\n * missing. `carriedOver` supplies the refresh pair a rotation response may\n * legally omit (RFC 6749 §6: no replacement means keep using the presented\n * one); a login response has nothing to carry over, so a missing field there\n * is an error.\n */\nexport function agentSessionFromTokenResponse(\n body: Record<string, unknown>,\n carriedOver?: { refreshToken: string; refreshExpiresAt: string }\n): AgentSession {\n const token = typeof body.access_token === \"string\" ? body.access_token : undefined;\n const claims = decodeJwtPayload(required(token, \"access_token\"));\n\n return {\n token: token!,\n teamId: required(typeof claims?.team_id === \"string\" ? claims.team_id : undefined, \"team_id\"),\n agentId: required(typeof claims?.agent_id === \"string\" ? claims.agent_id : undefined, \"agent_id\"),\n expiresAt: required(\n typeof claims?.exp === \"number\" ? new Date(claims.exp * 1000).toISOString() : undefined,\n \"exp\"\n ),\n refreshToken: required(\n typeof body.refresh_token === \"string\" ? body.refresh_token : carriedOver?.refreshToken,\n \"refresh_token\"\n ),\n refreshExpiresAt: required(\n typeof body.refresh_expires_in === \"number\"\n ? new Date(Date.now() + body.refresh_expires_in * 1000).toISOString()\n : carriedOver?.refreshExpiresAt,\n \"refresh_expires_in\"\n ),\n };\n}\n\n/** Every door stores the same shape, so the rest of the CLI cannot tell them apart. */\nexport function persistAgentSession(session: AgentSession): void {\n saveCredential({ tokenType: \"agent\", ...session });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Opt-in debug log. When a command is given `--log-file <path>` (or the\n * ANIMA_LOG_FILE env var is set), every network step appends one JSON line to\n * that file. Off by default and a no-op until enabled, so it never touches\n * stdout/stderr. Secret-bearing keys (tokens, auth headers) are redacted.\n *\n * Writes are synchronous (appendFileSync) so nothing is lost when a command\n * ends with process.exit() on an error path.\n */\n\nlet logPath: string | null = null;\n\nconst REDACT_KEY = /token|authorization|secret|password|_auth|api[-_]?key/i;\nconst REDACTED = \"***REDACTED***\";\n\nexport function initLogger(filePath?: string): void {\n const target = filePath || process.env.ANIMA_LOG_FILE;\n if (!target || logPath) return;\n logPath = path.resolve(target);\n fs.mkdirSync(path.dirname(logPath), { recursive: true });\n logEvent(\"log_started\", { pid: process.pid, argv: process.argv.slice(2) });\n}\n\nexport function logEvent(event: string, data?: Record<string, unknown>): void {\n if (!logPath) return;\n const entry = { ts: new Date().toISOString(), event, ...(data ? redact(data) : {}) };\n fs.appendFileSync(logPath, JSON.stringify(entry) + \"\\n\");\n}\n\nfunction redact(value: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (REDACT_KEY.test(key)) {\n out[key] = REDACTED;\n } else if (val && typeof val === \"object\" && !Array.isArray(val)) {\n out[key] = redact(val as Record<string, unknown>);\n } else {\n out[key] = val;\n }\n }\n return out;\n}\n","import { readCredentials, saveCredential, clearStorage } from \"./store.js\";\nimport { agentSessionFromTokenResponse, type AgentSession } from \"./agentSession.js\";\nimport { authError, apiError } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * Exchange a refresh token for a new access token (RFC 6749 §6).\n *\n * Refresh tokens are single use: every exchange returns a new one, and\n * presenting a spent one outside the server's rotation leeway revokes the whole\n * family. So the new pair is persisted before it is returned.\n */\nconst REFRESH_GRANT_TYPE = \"refresh_token\";\n\n/**\n * An OAuth error is `{error: \"code\", error_description}` (RFC 6749 §5.2), but a\n * misdirected request can land on something that answers in its own shape — a\n * framework validation error, a proxy, an older API. Read both without letting\n * an object reach the message, where it prints as `[object Object]` and tells\n * the operator nothing.\n */\nfunction readFailure(body: Record<string, unknown>): { code: string | null; message: string | null } {\n const raw = body.error;\n const nested = typeof raw === \"object\" && raw !== null ? (raw as Record<string, unknown>) : null;\n const code =\n typeof raw === \"string\"\n ? raw\n : typeof nested?.code === \"string\"\n ? nested.code\n : typeof nested?.error === \"string\"\n ? nested.error\n : null;\n\n const described = typeof body.error_description === \"string\" ? body.error_description : null;\n const message = described ?? (typeof raw === \"string\" ? raw : raw == null ? null : JSON.stringify(raw));\n return { code, message };\n}\n\nexport async function refreshAccessToken(\n apiUrl: string,\n carriedOver: { refreshToken: string; refreshExpiresAt: string },\n fetchFn: typeof fetch = fetch\n): Promise<AgentSession> {\n const base = apiUrl.replace(/\\/$/, \"\");\n const response = await fetchFn(`${base}/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: REFRESH_GRANT_TYPE,\n refresh_token: carriedOver.refreshToken,\n }).toString(),\n });\n\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n const failure = readFailure(body);\n logEvent(\"refresh_token_response\", { status: response.status, error: failure.code });\n\n if (!response.ok || typeof body.access_token !== \"string\") {\n // Dead credential: agent revoked, consent expired, or the token already\n // replaced. Nothing retryable, so drop the pair rather than leave one that\n // fails on every command.\n if (failure.code === \"invalid_grant\") {\n clearStorage();\n throw authError(`${failure.message ?? \"Your credentials are no longer valid\"}\\nRun: anima login`);\n }\n throw apiError(\n `Could not refresh credentials (HTTP ${response.status})${failure.message ? `: ${failure.message}` : \"\"}`\n );\n }\n\n const session = agentSessionFromTokenResponse(body, carriedOver);\n saveCredential({ tokenType: \"agent\", ...session });\n return session;\n}\n\n/**\n * Revoke the stored refresh token server-side (RFC 7009), killing every\n * credential descended from the same consent. Best effort: logout must clear\n * the machine even when the server is unreachable.\n */\nexport async function revokeStoredRefreshToken(\n apiUrl: string,\n fetchFn: typeof fetch = fetch\n): Promise<boolean> {\n const creds = readCredentials();\n if (creds?.tokenType !== \"agent\") return false;\n\n try {\n const response = await fetchFn(`${apiUrl.replace(/\\/$/, \"\")}/oauth/revoke`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ token: creds.refreshToken, token_type_hint: \"refresh_token\" }).toString(),\n });\n logEvent(\"revoke_response\", { status: response.status });\n return response.ok;\n } catch (err) {\n logEvent(\"revoke_failed\", { error: err instanceof Error ? err.message : String(err) });\n return false;\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\n/**\n * Persistent, non-secret CLI preferences (e.g. a default API URL for local\n * development). Kept separate from credentials.json so `anima logout` never\n * wipes your machine config. Manage it with `anima config`.\n */\n\nconst CONFIG_DIR = path.join(os.homedir(), \".config\", \"anima\");\nconst CONFIG_FILE = path.join(CONFIG_DIR, \"config.json\");\n\nexport const DEFAULT_API_URL = \"https://api.agentgrid.io\";\n\nexport type Config = {\n apiUrl?: string;\n};\n\n/** User-facing config keys (kebab) mapped to their stored (camel) field. */\nexport const CONFIG_KEYS = {\n \"api-url\": \"apiUrl\",\n} as const satisfies Record<string, keyof Config>;\n\nexport type ConfigKey = keyof typeof CONFIG_KEYS;\n\nexport function isConfigKey(key: string): key is ConfigKey {\n return key in CONFIG_KEYS;\n}\n\nexport function configKeys(): ConfigKey[] {\n return Object.keys(CONFIG_KEYS) as ConfigKey[];\n}\n\nexport function readConfig(): Config {\n try {\n if (!fs.existsSync(CONFIG_FILE)) return {};\n const parsed = JSON.parse(fs.readFileSync(CONFIG_FILE, \"utf-8\"));\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n return {};\n }\n}\n\nexport function setConfig(key: ConfigKey, value: string): void {\n const merged = { ...readConfig(), [CONFIG_KEYS[key]]: value };\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + \"\\n\");\n}\n\n/** Remove one key; returns whether it was set. */\n/** Remove the whole config file (used by logout — full machine reset). */\nexport function deleteConfig(): boolean {\n try {\n if (!fs.existsSync(CONFIG_FILE)) return false;\n fs.unlinkSync(CONFIG_FILE);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function unsetConfig(key: ConfigKey): boolean {\n const config = readConfig();\n const field = CONFIG_KEYS[key];\n if (!(field in config)) return false;\n delete config[field];\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + \"\\n\");\n return true;\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n\n/**\n * Resolve the API base URL. Precedence: explicit flag → ANIMA_API_URL env →\n * stored config → built-in default.\n */\nexport function resolveApiUrl(flagValue?: string): string {\n return flagValue || process.env.ANIMA_API_URL || readConfig().apiUrl || DEFAULT_API_URL;\n}\n","import { classifyCredentials, getCredentialsPath } from \"./store.js\";\nimport { refreshAccessToken } from \"./refresh.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { authError } from \"../api/errors.js\";\n\nexport type ResolvedAuth = {\n token: string;\n teamId?: string;\n figmaToken?: string;\n source: \"env\" | \"file\";\n tokenType?: \"agent\" | \"account\";\n};\n\n/**\n * Renew this far ahead of expiry so a command that takes a while to run does\n * not have its token die mid-flight.\n */\nconst RENEW_BEFORE_EXPIRY_MS = 60_000;\n\nfunction needsRenewal(expiresAt: string | undefined): boolean {\n if (!expiresAt) return false;\n const expiry = new Date(expiresAt).getTime();\n return Number.isNaN(expiry) || expiry - Date.now() <= RENEW_BEFORE_EXPIRY_MS;\n}\n\n/**\n * Resolve the credential for an API call, renewing it when the stored access\n * token is at or near expiry.\n *\n * `apiUrlOverride` should be the command's `--api-url` when it has one, so a\n * renewal targets the same server the request will.\n */\nexport async function resolveAuth(apiUrlOverride?: string): Promise<ResolvedAuth> {\n const stored = classifyCredentials();\n\n // 1. Environment variable (primary — what AI tools use). Nothing to renew:\n // this is a long-lived personal token supplied from outside.\n const envToken = process.env.ANIMA_API_TOKEN;\n if (envToken) {\n return {\n token: envToken,\n teamId: process.env.ANIMA_TEAM_ID,\n figmaToken: process.env.FIGMA_TOKEN || (\"figmaToken\" in stored ? stored.figmaToken : undefined),\n source: \"env\",\n };\n }\n\n // 2. Stored credentials file\n const figmaToken = process.env.FIGMA_TOKEN || (\"figmaToken\" in stored ? stored.figmaToken : undefined);\n\n if (stored.kind === \"agent\") {\n const { credential } = stored;\n if (needsRenewal(credential.expiresAt)) {\n const renewed = await refreshAccessToken(resolveApiUrl(apiUrlOverride), {\n refreshToken: credential.refreshToken,\n refreshExpiresAt: credential.refreshExpiresAt,\n });\n return { token: renewed.token, teamId: renewed.teamId, figmaToken, source: \"file\", tokenType: \"agent\" };\n }\n return {\n token: credential.token,\n teamId: credential.teamId,\n figmaToken,\n source: \"file\",\n tokenType: \"agent\",\n };\n }\n\n if (stored.kind === \"account\") {\n return {\n token: stored.credential.token,\n teamId: stored.credential.teamId,\n figmaToken,\n source: \"file\",\n tokenType: \"account\",\n };\n }\n\n if (stored.kind === \"malformed\") {\n throw authError(\n `Your credentials file is damaged or incomplete (${getCredentialsPath()}). Run: anima login`\n );\n }\n\n // 3. No token found\n throw authError(\"No credentials found. Run: anima login\\n(or set the ANIMA_API_TOKEN env var)\");\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { CallToolResultSchema, ErrorCode } from \"@modelcontextprotocol/sdk/types.js\";\nimport { apiError, timeoutError, CliError } from \"./errors.js\";\nimport { logEvent } from \"../output/log.js\";\nimport { version } from \"../version.js\";\n\n/**\n * The CLI talks to AgentGrid only through the MCP endpoint (`/v1/mcp`), the single\n * governed surface (see anima-design-to-code docs/grids/DECISIONS.md \"D47\").\n * Every command runs a tool through this client — there is no other transport.\n */\n\nconst MCP_PATH = \"/v1/mcp\";\n// MCP clientInfo version tracks package.json so server logs see the real release.\nconst CLIENT_INFO = { name: \"anima-cli\", version };\n\nexport type McpConfig = {\n apiBaseUrl: string;\n token: string;\n teamId?: string;\n /** Sent as X-Figma-Token; f2c tools read it from the header, not the args. */\n figmaToken?: string;\n};\n\n/** Progress reported by long-running tools (generation, deploy). */\nexport type ToolProgress = { progress: number; total?: number; message?: string };\n\nexport type CallToolOptions = {\n onProgress?: (p: ToolProgress) => void;\n /** Idle timeout; reset on each progress notification so long jobs don't trip it. */\n timeoutMs?: number;\n};\n\nconst DEFAULT_TIMEOUT_MS = 600_000;\n\nexport class AnimaMcpClient {\n #client: Client;\n #transport: StreamableHTTPClientTransport;\n #url: string;\n\n constructor(config: McpConfig) {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${config.token}`,\n };\n if (config.teamId) headers[\"X-Team-Id\"] = config.teamId;\n if (config.figmaToken) headers[\"X-Figma-Token\"] = config.figmaToken;\n\n this.#url = new URL(MCP_PATH, config.apiBaseUrl).toString();\n this.#transport = new StreamableHTTPClientTransport(new URL(this.#url), {\n requestInit: { headers },\n });\n this.#client = new Client(CLIENT_INFO, { capabilities: {} });\n }\n\n async connect(): Promise<void> {\n logEvent(\"mcp_connect\", { url: this.#url });\n try {\n await this.#client.connect(this.#transport);\n } catch (err) {\n logEvent(\"mcp_connect_failed\", { url: this.#url, error: (err as Error)?.message });\n throw connectionError(err);\n }\n }\n\n /**\n * Call a tool and return its parsed result. Anima tools return a single JSON\n * text block; a `{ success: false }` payload is a normal result, so callers\n * still inspect `success` themselves.\n */\n async callTool<T = unknown>(\n name: string,\n args: Record<string, unknown>,\n options: CallToolOptions = {}\n ): Promise<T> {\n logEvent(\"mcp_tool_call\", { tool: name, arguments: args });\n let result;\n try {\n result = await this.#client.callTool(\n { name, arguments: args },\n CallToolResultSchema,\n {\n timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n resetTimeoutOnProgress: true,\n onprogress: options.onProgress\n ? (p) => options.onProgress!({ progress: p.progress, total: p.total, message: p.message })\n : undefined,\n }\n );\n } catch (err) {\n logEvent(\"mcp_tool_error\", { tool: name, error: (err as Error)?.message });\n if ((err as { code?: number })?.code === ErrorCode.RequestTimeout) {\n throw timeoutError();\n }\n throw err;\n }\n logEvent(\"mcp_tool_result\", { tool: name, isError: result.isError ?? false });\n\n const content = Array.isArray(result.content) ? result.content : [];\n const text = content.find((c): c is { type: \"text\"; text: string } => c.type === \"text\")?.text;\n\n if (result.isError) {\n throw apiError(text || \"MCP tool returned an error\");\n }\n if (!text) {\n throw apiError(\"MCP tool returned no text content\");\n }\n\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as T;\n }\n }\n\n async close(): Promise<void> {\n await this.#transport.close().catch(() => {});\n }\n}\n\n/** Connect, run `fn`, and always close the transport. */\nexport async function withMcp<T>(\n config: McpConfig,\n fn: (client: AnimaMcpClient) => Promise<T>\n): Promise<T> {\n const client = new AnimaMcpClient(config);\n await client.connect();\n try {\n return await fn(client);\n } finally {\n await client.close();\n }\n}\n\nfunction connectionError(err: unknown): CliError {\n const message = err instanceof Error ? err.message : String(err);\n return new CliError(\n \"CONNECTION_ERROR\",\n `Could not reach the AgentGrid MCP endpoint: ${message}`,\n 1\n );\n}\n","import { createRequire } from \"node:module\";\n\n// Single source for the CLI version: package.json. `../package.json` resolves\n// from src/ in dev and from dist/index.js in the published bundle — this file\n// must stay directly under src/ for that to hold.\nexport const { version } = createRequire(import.meta.url)(\"../package.json\") as { version: string };\n","export type OutputMode = \"json\" | \"pretty\";\n\nexport function detectOutputMode(flags: {\n json?: boolean;\n}): OutputMode {\n if (flags.json !== undefined) {\n return flags.json ? \"json\" : \"pretty\";\n }\n // Auto-detect: JSON when piped, pretty in TTY\n return process.stdout.isTTY ? \"pretty\" : \"json\";\n}\n\nexport function outputResult(mode: OutputMode, data: unknown): void {\n if (mode === \"json\") {\n process.stdout.write(JSON.stringify(data) + \"\\n\");\n }\n // Pretty mode output is handled inline by commands using chalk/ora\n}\n\nexport function outputError(\n mode: OutputMode,\n error: { code: string; message: string }\n): void {\n if (mode === \"json\") {\n process.stdout.write(\n JSON.stringify({ success: false, error }) + \"\\n\"\n );\n }\n // Pretty mode errors are handled inline by commands\n}\n","import ora, { type Ora } from \"ora\";\nimport type { OutputMode } from \"./formatter.js\";\n\nexport class ProgressReporter {\n #spinner: Ora | null = null;\n #mode: OutputMode;\n #startTime: number = 0;\n #verbose: boolean;\n\n constructor(mode: OutputMode, verbose: boolean = false) {\n this.#mode = mode;\n this.#verbose = verbose;\n }\n\n start(message: string): void {\n this.#startTime = Date.now();\n if (this.#mode === \"pretty\") {\n // A previous phase's spinner must be stopped first: an orphaned ora\n // interval keeps the event loop (and its repaints) alive forever.\n this.#spinner?.stop();\n this.#spinner = ora(message).start();\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"started\", message }) + \"\\n\");\n }\n }\n\n update(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.text = `${message} ${elapsed}`;\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"progress\", message }) + \"\\n\");\n }\n }\n\n succeed(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.succeed(`${message} ${elapsed}`);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"done\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n fail(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n this.#spinner.fail(message);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"error\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n #elapsed(): string {\n const ms = Date.now() - this.#startTime;\n const seconds = Math.floor(ms / 1000);\n if (seconds < 60) return `(${seconds}s)`;\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `(${minutes}m ${secs}s)`;\n }\n}\n","import chalk from \"chalk\";\n\nexport function printSuccess(message: string): void {\n console.log(chalk.green(\"✓\") + \" \" + message);\n}\n\nexport function printError(message: string): void {\n console.error(chalk.red(\"✗\") + \" \" + message);\n}\n\nexport function printInfo(message: string): void {\n console.log(chalk.blue(\"ℹ\") + \" \" + message);\n}\n\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(\"⚠\") + \" \" + message);\n}\n\nexport function printKeyValue(key: string, value: string): void {\n console.log(` ${chalk.gray(key + \":\")} ${value}`);\n}\n\nexport function printSessionResult(result: {\n sessionId: string;\n playgroundUrl?: string;\n tokenUsage?: number;\n}): void {\n console.log();\n printSuccess(\"Artifact created successfully!\");\n printKeyValue(\"Session ID\", result.sessionId);\n if (result.playgroundUrl) {\n printKeyValue(\"Your artifact\", chalk.cyan.underline(result.playgroundUrl));\n }\n if (result.tokenUsage) {\n printKeyValue(\"Token usage\", result.tokenUsage.toLocaleString());\n }\n console.log();\n}\n\nexport function printDeployResult(result: { url?: string }): void {\n console.log();\n printSuccess(\"Published successfully!\");\n if (result.url) {\n printKeyValue(\"Live URL\", chalk.cyan.underline(result.url));\n }\n console.log();\n}\n\nexport function printFilesWritten(outputDir: string, count: number): void {\n console.log();\n printSuccess(`${count} files written to ${chalk.cyan(outputDir)}`);\n console.log();\n}\n","/**\n * Parse a Figma URL to extract fileKey and nodeId.\n *\n * Supported formats:\n * - https://www.figma.com/file/ABC123/FileName?node-id=42-15\n * - https://www.figma.com/design/ABC123/FileName?node-id=42-15\n * - https://figma.com/file/ABC123/FileName?node-id=42%3A15\n * - Just a fileKey string\n */\nexport function parseFigmaUrl(input: string): {\n fileKey: string;\n nodeId?: string;\n} {\n // If it doesn't look like a URL, treat as a raw file key\n if (!input.includes(\"figma.com\")) {\n return { fileKey: input };\n }\n\n try {\n const url = new URL(input);\n const pathParts = url.pathname.split(\"/\").filter(Boolean);\n\n // Expected format: /file/KEY/name or /design/KEY/name\n const typeIndex = pathParts.findIndex(\n (p) => p === \"file\" || p === \"design\"\n );\n if (typeIndex === -1 || typeIndex + 1 >= pathParts.length) {\n throw new Error(\"Could not find file key in Figma URL\");\n }\n\n const fileKey = pathParts[typeIndex + 1];\n const nodeIdParam = url.searchParams.get(\"node-id\");\n\n let nodeId: string | undefined;\n if (nodeIdParam) {\n // Convert dash format (42-15) to colon format (42:15)\n nodeId = nodeIdParam.replace(/-/g, \":\");\n }\n\n return { fileKey, nodeId };\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"file key\")) {\n throw err;\n }\n throw new Error(`Invalid Figma URL: ${input}`);\n }\n}\n\n/**\n * Normalize a node ID: convert dash format to colon format.\n * \"42-15\" -> \"42:15\"\n */\nexport function normalizeNodeId(nodeId: string): string {\n return nodeId.replace(/-/g, \":\");\n}\n","import { readdirSync, readFileSync, statSync } from \"fs\";\nimport { join, relative, extname } from \"path\";\nimport AdmZip from \"adm-zip\";\n\n/**\n * Collect a local project for `create -t import --from <path>`.\n *\n * Two transports, mirroring the server's contract:\n * - inline: small, text-only projects → `files` map on artifact-create\n * - zip: anything with binaries or over the inline caps, or a .zip given\n * directly → artifact-get_zip_upload_url + PUT + zipUploadId\n */\n\nconst SKIPPED_DIRS = new Set([\".git\", \"node_modules\", \"dist\", \"build\", \".next\", \"out\", \"coverage\", \".turbo\", \".cache\"]);\n\nconst BINARY_EXTENSIONS = new Set([\n \".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".ico\", \".bmp\",\n \".woff\", \".woff2\", \".ttf\", \".otf\", \".eot\",\n \".mp4\", \".webm\", \".mp3\", \".wav\", \".ogg\",\n \".zip\", \".tar\", \".gz\", \".pdf\", \".wasm\",\n]);\n\n/** Server-side inline caps (kept in sync with artifact-create). */\nconst MAX_INLINE_FILES = 1000;\nconst MAX_INLINE_BYTES = 10 * 1024 * 1024;\n\nexport type ProjectSource =\n | { kind: \"files\"; files: Record<string, string>; fileCount: number }\n | { kind: \"zip\"; buffer: Buffer; reason: string };\n\nfunction walk(root: string, dir: string, out: string[]): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (!SKIPPED_DIRS.has(entry.name)) walk(root, join(dir, entry.name), out);\n } else if (entry.isFile()) {\n out.push(relative(root, join(dir, entry.name)));\n }\n }\n}\n\nfunction zipFolder(root: string): Buffer {\n const zip = new AdmZip();\n zip.addLocalFolder(root, \"\", (entryPath) => {\n const segments = entryPath.split(/[\\\\/]/);\n return !segments.some((segment) => SKIPPED_DIRS.has(segment));\n });\n return zip.toBuffer();\n}\n\nfunction isProbablyBinary(path: string, buffer: Buffer): boolean {\n if (BINARY_EXTENSIONS.has(extname(path).toLowerCase())) return true;\n return buffer.includes(0);\n}\n\n/**\n * Read a folder or .zip into the transport the server expects.\n * Never sends binaries inline: any binary file, or exceeding the inline caps,\n * switches the whole project to the zip transport.\n */\nexport function collectProjectSource(fromPath: string): ProjectSource {\n const stats = statSync(fromPath);\n\n if (stats.isFile()) {\n if (extname(fromPath).toLowerCase() !== \".zip\") {\n throw new Error(`--from must be a folder or a .zip file, got: ${fromPath}`);\n }\n return { kind: \"zip\", buffer: readFileSync(fromPath), reason: \"zip file given\" };\n }\n\n const paths: string[] = [];\n walk(fromPath, fromPath, paths);\n if (paths.length === 0) {\n throw new Error(`--from folder is empty: ${fromPath}`);\n }\n if (paths.length > MAX_INLINE_FILES) {\n return { kind: \"zip\", buffer: zipFolder(fromPath), reason: `${paths.length} files exceeds the inline limit` };\n }\n\n const files: Record<string, string> = {};\n let totalBytes = 0;\n for (const path of paths) {\n const buffer = readFileSync(join(fromPath, path));\n if (isProbablyBinary(path, buffer)) {\n return { kind: \"zip\", buffer: zipFolder(fromPath), reason: `binary file present (${path})` };\n }\n totalBytes += buffer.length;\n if (totalBytes > MAX_INLINE_BYTES) {\n return { kind: \"zip\", buffer: zipFolder(fromPath), reason: \"project exceeds the inline size limit\" };\n }\n // Normalize Windows separators — the server rejects backslashes\n files[path.split(\"\\\\\").join(\"/\")] = buffer.toString(\"utf8\");\n }\n\n return { kind: \"files\", files, fileCount: paths.length };\n}\n","/** Base for the user-facing playground link: `${BASE}/<sessionId>`. */\nexport const PLAYGROUND_BASE = \"https://dev.animaapp.com/chat\";\n\n/**\n * Parse a playground URL to extract the session ID.\n * Supported formats:\n * - https://dev.animaapp.com/chat/SESSION_ID\n * - https://app.agentgrid.io/artifacts/SESSION_ID\n * - Just a session ID string\n */\nexport function parsePlaygroundUrl(input: string): string {\n if (!input.includes(\"/\")) {\n return input;\n }\n\n try {\n const url = new URL(input);\n const parts = url.pathname.split(\"/\").filter(Boolean);\n // Expected: /chat/SESSION_ID or /artifacts/SESSION_ID — the session id is\n // the segment after either marker.\n const markerIndex = parts.findIndex((p) => p === \"chat\" || p === \"artifacts\");\n if (markerIndex !== -1 && markerIndex + 1 < parts.length) {\n return parts[markerIndex + 1];\n }\n // Fallback: last path segment\n return parts[parts.length - 1];\n } catch {\n // Not a URL, treat as session ID\n return input;\n }\n}\n","import { apiError } from \"./errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * The anonymous fast track: create an artifact with no account and no\n * credential at all.\n *\n * This is the one path that cannot go through MCP, because every MCP tool call\n * carries a bearer token and the whole point here is that there isn't one yet.\n * It talks to the public REST endpoints directly, and hands back the handoff\n * token that `anima login --handoff` later trades for a real credential.\n */\n\nexport type AnonymousCreateRequest = {\n apiUrl: string;\n files?: Record<string, string>;\n zipUploadId?: string;\n framework?: string;\n artifactType?: string;\n name?: string;\n /** Groups this artifact into an existing anonymous bucket. */\n handoffToken?: string;\n clientName?: string;\n};\n\nexport type AnonymousCreateResult = {\n sessionId: string;\n handoffToken: string;\n /**\n * The artifact's page: where a human views it, and where they take ownership\n * while it is still unclaimed — server-supplied, not built here.\n */\n artifactUrl: string;\n claimableUntil: string;\n framework?: string;\n fileCount?: number;\n skippedFiles?: string[];\n notes?: string;\n nextSteps?: string;\n};\n\nexport async function createAnonymousArtifact(\n request: AnonymousCreateRequest,\n fetchFn: typeof fetch = fetch\n): Promise<AnonymousCreateResult> {\n const url = `${request.apiUrl.replace(/\\/$/, \"\")}/v1/generationSessions`;\n // Only `import` exists anonymously — the server rejects `empty` (there would\n // be no way to push to it) and assets (they need a team to belong to).\n const body = {\n type: \"import\",\n ...(request.files ? { files: request.files } : {}),\n ...(request.zipUploadId ? { zipUploadId: request.zipUploadId } : {}),\n ...(request.framework ? { framework: request.framework } : {}),\n ...(request.artifactType ? { artifactType: request.artifactType } : {}),\n ...(request.name ? { name: request.name } : {}),\n ...(request.handoffToken ? { handoffToken: request.handoffToken } : {}),\n ...(request.clientName ? { clientName: request.clientName } : {}),\n };\n\n logEvent(\"anonymous_create_request\", { url, type: \"import\", artifactType: request.artifactType });\n const response = await fetchFn(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n const payload = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n logEvent(\"anonymous_create_response\", { url, status: response.status, error: payload.error });\n\n if (!response.ok || payload.success !== true) {\n const message =\n (typeof payload.reason === \"string\" && payload.reason) ||\n (typeof payload.error === \"string\" && payload.error) ||\n `Anonymous create failed (HTTP ${response.status})`;\n const nextSteps = typeof payload.nextSteps === \"string\" ? payload.nextSteps : undefined;\n throw apiError(nextSteps ? `${message}\\n${nextSteps}` : message, payload);\n }\n\n // A create that returned no handoff token is not usable as a fast track: the\n // artifact could never be claimed, so fail here rather than after the caller\n // has already reported success.\n for (const field of [\"sessionId\", \"handoffToken\", \"artifactUrl\", \"claimableUntil\"] as const) {\n if (typeof payload[field] !== \"string\") {\n throw apiError(`The API's create response is missing \\`${field}\\`.`, payload);\n }\n }\n\n return payload as unknown as AnonymousCreateResult;\n}\n\n/** Reserve an anonymous staging slot for a project too large to send inline. */\nexport async function getAnonymousZipUploadUrl(\n apiUrl: string,\n fetchFn: typeof fetch = fetch\n): Promise<{ zipUploadId: string; uploadUrl: string }> {\n const url = `${apiUrl.replace(/\\/$/, \"\")}/v1/generationSessions/zip-upload-url`;\n const response = await fetchFn(url, { method: \"POST\" });\n const payload = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n\n if (!response.ok || payload.success !== true || typeof payload.uploadUrl !== \"string\") {\n const message =\n (typeof payload.reason === \"string\" && payload.reason) ||\n (typeof payload.error === \"string\" && payload.error) ||\n `Could not get a zip upload URL (HTTP ${response.status})`;\n throw apiError(message, payload);\n }\n\n return { zipUploadId: payload.zipUploadId as string, uploadUrl: payload.uploadUrl };\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { PLAYGROUND_BASE } from \"../utils/playgroundUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `workspace-list_artifacts` MCP tool. Lists the team's artifacts\n * most-recently-updated first so an agent can resume existing work instead of\n * creating duplicates.\n */\n\ntype Artifact = {\n id?: string;\n name: string;\n type: \"app\" | \"markdown\" | \"asset\";\n sessionId?: string;\n updatedAt: string;\n registered: boolean;\n};\n\ntype ListArtifactsResult = {\n success: boolean;\n workspaceId?: string;\n artifacts?: Artifact[];\n truncated?: boolean;\n error?: string;\n reason?: string;\n};\n\nexport const listCommand = new Command(\"list\")\n .aliases([\"ls\", \"artifacts\"])\n .description(\n \"List your team's artifacts (most-recently-updated first) so you can resume existing work.\"\n )\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n try {\n const auth = await resolveAuth(opts.apiUrl);\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<ListArtifactsResult>(\"workspace-list_artifacts\", {})\n );\n\n if (!result.success) {\n const message = result.reason || result.error || \"Could not list artifacts\";\n throw apiError(message, result);\n }\n\n const artifacts = result.artifacts ?? [];\n logEvent(\"artifacts_listed\", { count: artifacts.length, truncated: result.truncated ?? false });\n\n if (mode === \"pretty\") {\n if (artifacts.length === 0) {\n console.log();\n console.log(\n \" No artifacts yet — create one with `create -t empty` or `create -t import`.\"\n );\n console.log();\n } else {\n console.log();\n for (const a of artifacts) {\n console.log(` ${chalk.bold(a.name)} ${chalk.gray(`(${a.type})`)}`);\n if (a.sessionId) {\n console.log(` ${chalk.gray(\"session:\")} ${a.sessionId}`);\n }\n console.log(` ${chalk.gray(\"updated:\")} ${formatUpdatedAt(a.updatedAt)}`);\n if (a.sessionId) {\n console.log(\n ` ${chalk.cyan.underline(`${PLAYGROUND_BASE}/${a.sessionId}`)}`\n );\n }\n console.log();\n }\n if (result.truncated) {\n console.log(\n chalk.yellow(\" The list was capped — some artifacts are not shown.\")\n );\n console.log();\n }\n }\n } else {\n outputResult(mode, {\n success: true,\n workspaceId: result.workspaceId,\n artifacts,\n truncated: result.truncated ?? false,\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\n/** Human-friendly \"x ago\" with the ISO timestamp in parentheses. */\nfunction formatUpdatedAt(iso: string): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) return iso;\n\n const seconds = Math.max(0, Math.round((Date.now() - then) / 1000));\n const relative =\n seconds < 60\n ? \"just now\"\n : seconds < 3600\n ? `${Math.floor(seconds / 60)}m ago`\n : seconds < 86400\n ? `${Math.floor(seconds / 3600)}h ago`\n : `${Math.floor(seconds / 86400)}d ago`;\n\n return `${relative} (${iso})`;\n}\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printDeployResult } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\nexport const publishCommand = new Command(\"publish\")\n .description(\"Deploy an artifact's app to a live public URL (1-3 min)\")\n .argument(\"<sessionId>\", \"Session ID from create command\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (sessionId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(\"Publishing...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n client.callTool<Record<string, unknown>>(\"artifact-publish\", { sessionId }, {\n onProgress: (p) => progress.update(p.message ?? \"Publishing...\"),\n })\n );\n\n if (!result.success) {\n throw new CliError(\n \"API_ERROR\",\n (result.error as string) || (result.reason as string) || \"Publish failed\",\n 1,\n result\n );\n }\n\n progress.succeed(\"Published!\");\n\n if (mode === \"pretty\") {\n printDeployResult({ url: result.liveUrl as string | undefined });\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n ...(result.liveUrl ? { liveUrl: result.liveUrl, subdomain: result.subdomain } : {}),\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printFilesWritten } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { writeFilesToDisk } from \"../utils/files.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\ntype CodegenResult = {\n success: boolean;\n sessionId?: string;\n files?: AnimaFiles;\n tokenUsage?: number;\n error?: string;\n reason?: string;\n};\n\nexport const codegenCommand = new Command(\"codegen\")\n .description(\"Convert Figma design to code files (no artifact)\")\n .requiredOption(\"--file-key <key>\", \"Figma file key or URL\")\n .option(\"--nodes <nodes>\", \"Figma node IDs, comma-separated\")\n .option(\"--figma-token <token>\", \"Figma personal access token (or set FIGMA_TOKEN env var)\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./generated\")\n .option(\"--framework <fw>\", \"react | html\", \"react\")\n .option(\"--styling <style>\", \"tailwind | plain_css\", \"tailwind\")\n .option(\"--language <lang>\", \"typescript | javascript\")\n .option(\"--ui-library <lib>\", \"mui | antd | shadcn | clean_react\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n: string) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n\n if (nodesId.length === 0) {\n throw validationError(\n \"No node IDs provided. Use --nodes or include node-id in the Figma URL.\"\n );\n }\n\n const auth = await resolveAuth(opts.apiUrl);\n\n // Resolve Figma token: flag > env var > stored credentials > error.\n // Sent via the X-Figma-Token header; the tool reads it from the header.\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || auth.figmaToken;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n\n // Default language to typescript when framework is react.\n const language = opts.language ?? (opts.framework === \"react\" ? \"typescript\" : undefined);\n\n const args: Record<string, unknown> = {\n fileKey,\n nodesId,\n framework: opts.framework,\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n progress.start(\"Generating code from Figma...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId, figmaToken },\n (client) =>\n client.callTool<CodegenResult>(\"codegen-figma_to_code\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.files) {\n throw apiError(result.reason || result.error || \"Code generation failed\", result);\n }\n\n const count = writeFilesToDisk(result.files, opts.output);\n\n progress.succeed(`Generated ${count} files`);\n\n if (mode === \"pretty\") {\n printFilesWritten(opts.output, count);\n } else {\n outputResult(mode, {\n success: true,\n output: opts.output,\n fileCount: count,\n sessionId: result.sessionId,\n tokenUsage: result.tokenUsage,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\n/**\n * Write generated files to disk.\n * Handles both code (text) and binary (base64-encoded) files.\n */\nexport function writeFilesToDisk(\n files: AnimaFiles,\n outputDir: string\n): number {\n // Create output directory\n fs.mkdirSync(outputDir, { recursive: true });\n\n let count = 0;\n\n const resolvedOutput = path.resolve(outputDir);\n\n for (const [filePath, fileContent] of Object.entries(files)) {\n const fullPath = path.resolve(outputDir, filePath);\n\n if (!fullPath.startsWith(resolvedOutput + path.sep)) {\n throw new Error(`Path traversal detected: ${filePath}`);\n }\n\n // Create parent directories\n const dirPath = path.dirname(fullPath);\n fs.mkdirSync(dirPath, { recursive: true });\n\n if (fileContent.isBinary) {\n const buffer = Buffer.from(fileContent.content, \"base64\");\n fs.writeFileSync(fullPath, buffer);\n } else {\n fs.writeFileSync(fullPath, fileContent.content, \"utf-8\");\n }\n\n count++;\n }\n\n return count;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { parsePlaygroundUrl } from \"../utils/playgroundUrl.js\";\nimport { parseGitTokenResponse } from \"../utils/gitToken.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `artifact-get_git_token` MCP tool — git is the only content\n * plane for artifact code. This mints a short-lived, repo-scoped git remote\n * URL; the caller runs git itself:\n *\n * git clone <gitRemoteUrl> # read (and edit locally)\n * git push # rw access: updates the live artifact\n * git remote set-url origin <url> # after expiry: point the clone at a fresh URL\n *\n * The token expires within an hour and cannot be renewed — re-run this command\n * for a fresh URL.\n */\nexport const getGitTokenCommand = new Command(\"get-git-token\")\n .description(\"Mint a short-lived git remote URL for an artifact (clone/push with git)\")\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const sessionId = parsePlaygroundUrl(artifactUrl);\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(\"Requesting git access...\");\n\n const response = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n client.callTool<unknown>(\"artifact-get_git_token\", { sessionId })\n );\n\n const grant = parseGitTokenResponse(response);\n logEvent(\"git_token_granted\", { sessionId, access: grant.access, expiresAt: grant.expiresAt });\n\n progress.succeed(`Git access granted (${grant.access === \"rw\" ? \"read-write\" : \"read-only\"})`);\n\n if (mode === \"pretty\") {\n console.log();\n console.log(` ${chalk.cyan(`git clone ${grant.gitRemoteUrl}`)}`);\n console.log();\n if (grant.access === \"rw\") {\n console.log(\" Commit and push to update the live artifact.\");\n } else {\n console.log(\" Read-only: cloning works, pushing will be rejected.\");\n }\n if (grant.expiresAt) {\n console.log(\n ` The URL embeds a token that expires at ${grant.expiresAt} and cannot be renewed;\\n` +\n ` re-run this command and ${chalk.cyan(\"git remote set-url origin <new url>\")} to keep pushing.`\n );\n }\n console.log(\" Treat the URL as a secret — it grants access to this artifact.\");\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n gitRemoteUrl: grant.gitRemoteUrl,\n access: grant.access,\n expiresAt: grant.expiresAt,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { apiError } from \"../api/errors.js\";\n\n/**\n * Parsed outcome of the `artifact-get_git_token` MCP tool.\n *\n * The tool returns JSON: `{ success, gitRemoteUrl, access, expiresAt }` on a\n * grant, or `{ success: false, error, reason }` on a denial. The MCP client\n * (api/mcp.ts) already JSON-parses tool text, so this receives the parsed\n * object — a string only arrives if that parse failed. The clone URL embeds a\n * short-lived access token scoped to the one artifact.\n */\nexport type GitTokenGrant = {\n gitRemoteUrl: string;\n access: \"ro\" | \"rw\";\n expiresAt?: string;\n};\n\nfunction preview(payload: unknown): string {\n const text = typeof payload === \"string\" ? payload : JSON.stringify(payload);\n return (text ?? String(payload)).slice(0, 200);\n}\n\nexport function parseGitTokenResponse(payload: unknown): GitTokenGrant {\n let value = payload;\n if (typeof value === \"string\") {\n try {\n value = JSON.parse(value);\n } catch {\n throw apiError(`Unexpected response from artifact-get_git_token: ${preview(payload)}`);\n }\n }\n\n if (value === null || typeof value !== \"object\") {\n throw apiError(`Unexpected response from artifact-get_git_token: ${preview(payload)}`);\n }\n\n const body = value as {\n success?: boolean;\n error?: string;\n reason?: string;\n gitRemoteUrl?: string;\n access?: string;\n expiresAt?: string;\n };\n\n if (body.success === false) {\n throw apiError(`Git access ${body.error ?? \"denied\"}: ${(body.reason ?? \"\").trim()}`);\n }\n\n if (!body.gitRemoteUrl) {\n throw apiError(`Unexpected response from artifact-get_git_token: ${preview(payload)}`);\n }\n\n return {\n gitRemoteUrl: body.gitRemoteUrl,\n access: body.access === \"rw\" ? \"rw\" : \"ro\",\n expiresAt: body.expiresAt,\n };\n}\n","import { Command } from \"commander\";\nimport { buildMcpConfig } from \"./login.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printInfo } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * Print the MCP server config for this API. The client authorizes itself, so\n * this needs no credentials and makes no network call.\n */\nexport const mcpConfigCommand = new Command(\"mcp-config\")\n .description(\"Print an MCP server config for your MCP client\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n\n try {\n const mcpConfig = buildMcpConfig(resolveApiUrl(opts.apiUrl));\n\n if (mode === \"pretty\") {\n printInfo(\"MCP server config (add to your MCP client):\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n console.log();\n printInfo(\"Your client will prompt you to authorize on first use.\");\n } else {\n outputResult(mode, { success: true, mcpConfig });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { loginWithDeviceFlow } from \"../auth/device.js\";\nimport { loginWithInvite, parseInvite } from \"../auth/invite.js\";\nimport { loginWithHandoff } from \"../auth/handoff.js\";\nimport { getCredentialsPath, readPendingHandoff } from \"../auth/store.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { resolveApiUrl, setConfig, readConfig } from \"../config/store.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printSuccess, printError, printKeyValue, printInfo } from \"../output/pretty.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * `anima login` — connect this machine as a governed agent.\n *\n * Two doors, one credential store:\n * - Default: the OAuth device flow. The command prints a short code and a\n * verification URL; a human approves on any device — choosing which\n * workspaces and capabilities this agent gets — and the CLI picks up its\n * scoped token automatically.\n * - `--invite <url-or-code>`: redeem a pre-approved invite (the human already\n * consented in-app when minting it) — a single exchange, no human step and\n * no browser.\n * - `--handoff [token]`: redeem the token an anonymous create handed back. It\n * only becomes a credential once a human claims the artifact, so this waits.\n * Every door stores and renews its credentials the same way; logging in again\n * with the same agent name reconnects to the same agent identity.\n */\nexport const loginCommand = new Command(\"login\")\n .description(\"Log in via the device flow, redeem an invite with --invite, or finish an anonymous create with --handoff\")\n .option(\"--invite <url-or-code>\", \"Redeem an invite link (…/invite/<code>.md) or bare code — no approval step\")\n .option(\n \"--handoff [token]\",\n \"Log in with the handoff token from an anonymous create. Waits until a human claims the artifact. Defaults to your last one\"\n )\n .option(\"--client-name <name>\", \"How this CLI appears on the consent screen\", \"AgentGrid CLI\")\n .option(\"--no-open\", \"Do not try to open the verification page in a browser\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .option(\n \"--print-mcp-config\",\n \"After login, also print an MCP server config (URL only — the client authorizes itself) to paste into an MCP-capable agent\"\n )\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n if (opts.handoff) {\n await runHandoffLogin(opts, mode);\n return;\n }\n\n if (opts.invite) {\n // The invite URL was minted on the API the human used, so its origin is\n // the right base unless the caller explicitly overrides it.\n const inviteOrigin = parseInvite(opts.invite).origin;\n const apiUrl = opts.apiUrl ? resolveApiUrl(opts.apiUrl) : (inviteOrigin ?? resolveApiUrl());\n\n try {\n const result = await loginWithInvite({ apiUrl, invite: opts.invite });\n // Persist the origin the invite was redeemed on: the token is only\n // valid THERE, so later commands (get-git-token, mcp-config, …) must\n // default to it instead of the built-in API URL.\n if (inviteOrigin && readConfig().apiUrl !== apiUrl) {\n setConfig(\"api-url\", apiUrl);\n }\n const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n printKeyValue(\"Agent\", result.agentId);\n printKeyValue(\"Team ID\", result.teamId);\n printKeyValue(\"Token expires\", result.expiresAt);\n printInfo(\"This is a scoped agent token — it acts within what was approved, and the team can revoke it.\");\n if (mcpConfig) {\n console.log();\n printInfo(\"MCP server config — your client will prompt to authorize on first use:\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"logged_in\",\n via: \"invite\",\n tokenType: \"agent\",\n agentId: result.agentId,\n teamId: result.teamId,\n expiresAt: result.expiresAt,\n ...(mcpConfig ? { mcpConfig } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n return;\n }\n\n const apiUrl = resolveApiUrl(opts.apiUrl);\n\n try {\n const result = await loginWithDeviceFlow({\n apiUrl,\n clientName: opts.clientName,\n onVerification: (info) => {\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"To connect, open the verification page and enter this code:\");\n console.log();\n console.log(` ${chalk.cyan.underline(info.verificationUri)}`);\n console.log();\n console.log(` ${chalk.bold.white(info.userCode)}`);\n console.log();\n printInfo(`Waiting for approval… (code expires in ${Math.round(info.expiresInSeconds / 60)} minutes)`);\n } else {\n // JSON mode: emit the verification info to stderr so a wrapping\n // agent can surface it to its human while stdout stays reserved\n // for the final result object.\n process.stderr.write(\n JSON.stringify({\n event: \"verification_required\",\n verificationUri: info.verificationUri,\n verificationUriComplete: info.verificationUriComplete,\n userCode: info.userCode,\n expiresIn: info.expiresInSeconds,\n }) + \"\\n\"\n );\n }\n\n // Best-effort convenience in a terminal; the printed URL + code are\n // the real path (the whole point of the flow is that THIS machine\n // may have no browser).\n if (mode === \"pretty\" && opts.open) {\n open(info.verificationUriComplete).catch(() => {});\n }\n },\n });\n\n const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n printKeyValue(\"Agent\", result.agentId);\n printKeyValue(\"Team ID\", result.teamId);\n printKeyValue(\"Token expires\", result.expiresAt);\n printInfo(\"This is a scoped agent token — it acts within what you approved, and your team can revoke it.\");\n if (mcpConfig) {\n console.log();\n printInfo(\"MCP server config — your client will prompt to authorize on first use:\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"logged_in\",\n tokenType: \"agent\",\n agentId: result.agentId,\n teamId: result.teamId,\n expiresAt: result.expiresAt,\n ...(mcpConfig ? { mcpConfig } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\n/**\n * Redeem a handoff token: block until a human claims the artifact, then store\n * what the claim grants — the same storage every other login door uses. The\n * token is taken from the argument, or from the last anonymous create.\n */\nasync function runHandoffLogin(opts: Record<string, string>, mode: ReturnType<typeof detectOutputMode>) {\n // `--handoff` bare is `true`; `--handoff <token>` is the token itself. An\n // explicit token wins, so holding the token is always enough — the stored\n // record just saves passing it in the common case.\n const explicitToken = typeof opts.handoff === \"string\" ? opts.handoff : undefined;\n const stored = readPendingHandoff();\n const pending =\n stored && (!explicitToken || stored.handoffToken === explicitToken)\n ? stored\n : explicitToken\n ? { handoffToken: explicitToken, sessionId: \"\", artifactUrl: \"\", claimableUntil: \"\", apiUrl: resolveApiUrl() }\n : null;\n\n if (!pending) {\n const message =\n \"No handoff token. Pass one (`anima login --handoff <token>`), or run \" +\n \"`anima create --anonymous -t import --from <path>` to get one. \" +\n \"(Already logged in another way? `anima auth --status`.)\";\n if (mode === \"pretty\") {\n printError(message);\n } else {\n outputError(mode, { code: \"VALIDATION_ERROR\", message });\n }\n process.exit(1);\n }\n\n // The token is only redeemable on the origin that minted it, so the stored\n // one wins unless the caller explicitly overrides it.\n const apiUrl = opts.apiUrl ? resolveApiUrl(opts.apiUrl) : pending.apiUrl;\n\n try {\n // A token passed in by hand carries no claim metadata — only the record a\n // local create left behind knows the link and the deadline.\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"Waiting for a human to claim the artifact:\");\n if (pending.artifactUrl) {\n console.log();\n console.log(` ${chalk.cyan.underline(pending.artifactUrl)}`);\n }\n console.log();\n printInfo(\n pending.claimableUntil\n ? `Claimable until ${pending.claimableUntil}. Ctrl-C to stop — this does not cancel the claim.`\n : \"Ctrl-C to stop — this does not cancel the claim.\"\n );\n } else {\n // stdout stays reserved for the final result object, so a wrapping agent\n // can surface the link to its human from stderr while this blocks.\n process.stderr.write(\n JSON.stringify({\n event: \"claim_required\",\n ...(pending.artifactUrl ? { artifactUrl: pending.artifactUrl } : {}),\n ...(pending.sessionId ? { sessionId: pending.sessionId } : {}),\n ...(pending.claimableUntil ? { claimableUntil: pending.claimableUntil } : {}),\n }) + \"\\n\"\n );\n }\n\n const result = await loginWithHandoff({\n apiUrl,\n handoffToken: pending.handoffToken,\n claimableUntil: pending.claimableUntil || undefined,\n });\n\n if (readConfig().apiUrl !== apiUrl) {\n setConfig(\"api-url\", apiUrl);\n }\n const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Claimed — you're connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n printKeyValue(\"Agent\", result.agentId);\n printKeyValue(\"Team ID\", result.teamId);\n printKeyValue(\"Token expires\", result.expiresAt);\n printInfo(\"The artifact is now editable: anima get-git-token \" + pending.sessionId);\n if (mcpConfig) {\n console.log();\n printInfo(\"MCP server config — your client will prompt to authorize on first use:\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"logged_in\",\n via: \"handoff\",\n tokenType: \"agent\",\n agentId: result.agentId,\n teamId: result.teamId,\n expiresAt: result.expiresAt,\n sessionId: pending.sessionId,\n ...(mcpConfig ? { mcpConfig } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n}\n\n/**\n * A remote MCP server entry an MCP-capable agent can add to talk to Anima\n * directly (no CLI in the loop). Exact keys vary by client; this is the common\n * `mcpServers` shape. No credential: the client runs its own OAuth against the\n * server's advertised metadata and holds one it can renew, where a pasted\n * access token cannot be renewed by its holder. The URL honors\n * --api-url/config, so a local login yields a local config.\n */\nexport function buildMcpConfig(apiUrl: string) {\n return {\n mcpServers: {\n anima: {\n type: \"http\",\n url: `${apiUrl.replace(/\\/$/, \"\")}/v1/mcp`,\n },\n },\n };\n}\n","import { agentSessionFromTokenResponse, persistAgentSession, type AgentSession } from \"./agentSession.js\";\nimport { authError, CliError, EXIT_CODES } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * OAuth 2.0 Device Authorization Grant (RFC 8628) against the Anima\n * authorization server. The flow needs no browser on this machine: the server\n * returns a short human code, the human approves at the verification URL (any\n * device), and this client polls the token endpoint until the decision lands.\n *\n * The issued token is a scoped AGENT token: it acts within the workspaces and\n * capabilities the human approved on the consent screen, and the team can\n * revoke it at any time. Access tokens last 24 h and `resolveAuth` renews them\n * before they expire; running the flow again is only needed once the approval\n * itself ends (re-approval reconnects to the same agent when the same agent\n * name is kept).\n */\n\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst DEFAULT_CLIENT_NAME = \"AgentGrid CLI\";\n\nexport type DeviceVerificationInfo = {\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresInSeconds: number;\n};\n\n\ntype DeviceLoginOptions = {\n apiUrl: string;\n clientName?: string;\n /** Called once with the code the human must enter — the caller renders it. */\n onVerification: (info: DeviceVerificationInfo) => void;\n /** Injectable for tests. */\n fetchFn?: typeof fetch;\n sleepFn?: (ms: number) => Promise<void>;\n};\n\nconst defaultSleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\nexport async function loginWithDeviceFlow(options: DeviceLoginOptions): Promise<AgentSession> {\n const fetchFn = options.fetchFn ?? fetch;\n const sleep = options.sleepFn ?? defaultSleep;\n const base = options.apiUrl.replace(/\\/$/, \"\");\n\n // Step 1 — start the flow. No client registration: the server namespaces\n // device-flow agents itself; client_name is display-only on the consent page.\n const startUrl = `${base}/oauth/device_authorization`;\n logEvent(\"device_authorization_request\", { url: startUrl });\n const startResponse = await fetchFn(startUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ client_name: options.clientName ?? DEFAULT_CLIENT_NAME }).toString(),\n });\n logEvent(\"device_authorization_response\", { url: startUrl, status: startResponse.status });\n\n if (!startResponse.ok) {\n const detail = await startResponse.text().catch(() => \"\");\n logEvent(\"device_authorization_failed\", { url: startUrl, status: startResponse.status, body: detail.slice(0, 500) });\n const hint =\n startResponse.status === 404\n ? ` — no device endpoint at ${startUrl}. Check --api-url points to an API that has the device grant deployed.`\n : \"\";\n throw new CliError(\n \"API_ERROR\",\n `Device authorization failed (HTTP ${startResponse.status})${hint}`,\n EXIT_CODES.API_ERROR\n );\n }\n\n const start = (await startResponse.json()) as {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n };\n\n options.onVerification({\n userCode: start.user_code,\n verificationUri: start.verification_uri,\n verificationUriComplete: start.verification_uri_complete,\n expiresInSeconds: start.expires_in,\n });\n\n // Step 2 — poll until the human decides. The server enforces pacing:\n // slow_down means add 5 seconds to the interval (RFC 8628 §3.5).\n let intervalMs = Math.max(1, start.interval) * 1000;\n const deadline = Date.now() + start.expires_in * 1000;\n\n while (Date.now() < deadline) {\n await sleep(intervalMs);\n\n const pollResponse = await fetchFn(`${base}/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: DEVICE_GRANT_TYPE,\n device_code: start.device_code,\n }).toString(),\n });\n\n const body = (await pollResponse.json()) as Record<string, unknown>;\n logEvent(\"device_token_poll\", { status: pollResponse.status, error: body.error });\n\n if (pollResponse.ok && typeof body.access_token === \"string\") {\n const session = agentSessionFromTokenResponse(body);\n persistAgentSession(session);\n return session;\n }\n\n switch (body.error) {\n case \"authorization_pending\":\n continue;\n case \"slow_down\":\n intervalMs += 5000;\n continue;\n case \"access_denied\":\n throw authError(\"The authorization request was denied.\");\n case \"expired_token\":\n throw authError(\"The device code expired before approval. Run the login again.\");\n default:\n throw new CliError(\n \"API_ERROR\",\n `Unexpected token response: ${body.error ?? `HTTP ${pollResponse.status}`}`,\n EXIT_CODES.API_ERROR\n );\n }\n }\n\n throw authError(\"The device code expired before approval. Run the login again.\");\n}\n","import { agentSessionFromTokenResponse, persistAgentSession, type AgentSession } from \"./agentSession.js\";\nimport { CliError, EXIT_CODES } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * Invite-door redemption: exchange a pre-approved, single-use invite code for\n * a scoped agent token (`grant_type=urn:ietf:params:oauth:grant-type:\n * pre-authorized_code`) and store it exactly like the device login — so\n * `logout`, `mcp-config`, `get-git-token`, and the rest of the CLI work\n * identically for invited agents.\n *\n * The human mints the invite in-app and hands the agent a URL like\n * `https://api.agentgrid.io/invite/<code>.md`; this accepts either\n * that full URL or the bare code. A single POST returns the token directly —\n * there is no polling and no browser step (consent already happened at mint).\n */\n\nconst PRE_AUTHORIZED_GRANT = \"urn:ietf:params:oauth:grant-type:pre-authorized_code\";\n\n\nexport type ParsedInvite = {\n code: string;\n /** Origin of the invite URL, when a URL was given — the API the invite was minted on. */\n origin?: string;\n};\n\n/**\n * Accept the invite URL (`…/invite/<code>.md`), the same without `.md`, or the\n * bare code. When a URL is given, its origin is returned too: the invite was\n * minted on that host, so it is the right API base unless the caller overrides.\n */\nexport function parseInvite(input: string): ParsedInvite {\n const trimmed = input.trim();\n if (/^https?:\\/\\//i.test(trimmed)) {\n let url: URL;\n try {\n url = new URL(trimmed);\n } catch {\n throw new CliError(\"VALIDATION_ERROR\", `Not a valid invite URL: ${trimmed}`, EXIT_CODES.VALIDATION_ERROR);\n }\n const last = url.pathname.split(\"/\").filter(Boolean).pop() ?? \"\";\n const code = last.replace(/\\.md$/, \"\");\n if (!code) {\n throw new CliError(\n \"VALIDATION_ERROR\",\n \"The invite URL carries no code — expected …/invite/<code>.md\",\n EXIT_CODES.VALIDATION_ERROR\n );\n }\n return { code, origin: url.origin };\n }\n return { code: trimmed.replace(/\\.md$/, \"\") };\n}\n\ntype InviteLoginOptions = {\n apiUrl: string;\n invite: string;\n /** Injectable for tests. */\n fetchFn?: typeof fetch;\n};\n\nexport async function loginWithInvite(options: InviteLoginOptions): Promise<AgentSession> {\n const fetchFn = options.fetchFn ?? fetch;\n const { code } = parseInvite(options.invite);\n const base = options.apiUrl.replace(/\\/$/, \"\");\n\n const tokenUrl = `${base}/oauth/token`;\n logEvent(\"invite_redeem_request\", { url: tokenUrl });\n const response = await fetchFn(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: PRE_AUTHORIZED_GRANT,\n \"pre-authorized_code\": code,\n }).toString(),\n });\n\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n logEvent(\"invite_redeem_response\", { status: response.status, error: body.error });\n\n if (!response.ok || typeof body.access_token !== \"string\") {\n // The server's error_description is prompt-ware written for the agent —\n // surface it verbatim.\n const description =\n typeof body.error_description === \"string\"\n ? body.error_description\n : `Invite redemption failed (HTTP ${response.status})`;\n throw new CliError(\"AUTH_INVALID\", description, EXIT_CODES.AUTH_ERROR);\n }\n\n const session = agentSessionFromTokenResponse(body);\n persistAgentSession(session);\n\n return session;\n}\n","import { agentSessionFromTokenResponse, persistAgentSession, type AgentSession } from \"./agentSession.js\";\nimport { clearPendingHandoff } from \"./store.js\";\nimport { authError, CliError, EXIT_CODES } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * The handoff grant — the second half of the anonymous fast track.\n *\n * `anima create --anonymous` makes an artifact nobody owns yet and returns a\n * handoff token. A human opens the claim link and takes the artifact into their\n * team; if they also grant agent access, the claim leaves an access token\n * waiting for whoever holds the handoff token. This polls for it.\n *\n * Structurally the same as the device flow: one secret, polled against the same\n * token endpoint until a human decides. The differences are that the human here\n * decides on a claim page rather than a consent screen, and that the deadline\n * comes from the artifact's claim window rather than a device code's lifetime.\n */\n\nexport const HANDOFF_GRANT_TYPE = \"urn:animaapp:params:oauth:grant-type:handoff_token\";\n\n/** The server refuses polls closer than 15s apart; stay clear of that floor. */\nconst POLL_INTERVAL_SECONDS = 30;\n\nexport type HandoffLoginOptions = {\n apiUrl: string;\n handoffToken: string;\n /** ISO deadline to stop at — the bucket's claimableUntil. */\n claimableUntil?: string;\n /** Called before each wait, so a caller can show that it is still polling. */\n onPending?: (info: { nextPollInSeconds: number; deadline: Date }) => void;\n /** Injectable for tests. */\n fetchFn?: typeof fetch;\n sleepFn?: (ms: number) => Promise<void>;\n nowFn?: () => number;\n};\n\nconst defaultSleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\nexport async function loginWithHandoff(options: HandoffLoginOptions): Promise<AgentSession> {\n const fetchFn = options.fetchFn ?? fetch;\n const sleep = options.sleepFn ?? defaultSleep;\n const now = options.nowFn ?? Date.now;\n const base = options.apiUrl.replace(/\\/$/, \"\");\n const tokenUrl = `${base}/oauth/token`;\n\n const deadline = resolveDeadline(options.claimableUntil, now);\n let intervalMs = POLL_INTERVAL_SECONDS * 1000;\n\n // Poll first, wait second: the claim may already have happened (an agent can\n // run this long after the create), and the outcome is delivered to exactly\n // one poll — so sleeping first would only delay a token already waiting.\n for (;;) {\n const response = await fetchFn(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: HANDOFF_GRANT_TYPE,\n handoff_token: options.handoffToken,\n }).toString(),\n });\n\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n logEvent(\"handoff_token_poll\", { status: response.status, error: body.error });\n\n if (response.ok && typeof body.access_token === \"string\") {\n const session = agentSessionFromTokenResponse(body);\n persistAgentSession(session);\n // Redeemed: the token cannot produce another credential, so keeping it\n // would only offer a later poll a secret that can no longer work.\n clearPendingHandoff();\n return session;\n }\n\n switch (body.error) {\n case \"authorization_pending\":\n break;\n case \"slow_down\":\n intervalMs += 5000;\n break;\n case \"expired_token\":\n // Distinct from pending in a way that matters: no amount of further\n // polling changes this one, so say what to do instead of retrying.\n clearPendingHandoff();\n throw authError(\n \"This handoff token can no longer be redeemed — the claim window closed unclaimed, the token was \" +\n \"already redeemed, or the human claimed the artifact without granting agent access. \" +\n \"Share again with a new `anima create --anonymous` — or, if they claimed it and want you to keep \" +\n \"editing, have them grant your agent from the artifact page.\"\n );\n default:\n throw new CliError(\n \"API_ERROR\",\n `Unexpected token response: ${body.error ?? `HTTP ${response.status}`}`,\n EXIT_CODES.API_ERROR\n );\n }\n\n const remainingMs = deadline.getTime() - now();\n if (remainingMs <= 0) break;\n\n const waitMs = Math.min(intervalMs, remainingMs);\n options.onPending?.({ nextPollInSeconds: Math.round(waitMs / 1000), deadline });\n await sleep(waitMs);\n }\n\n throw authError(\n \"The claim window closed before anyone claimed the artifact. Share again with a new \" +\n \"`anima create --anonymous` — the previous one has expired and can no longer be claimed.\"\n );\n}\n\n/**\n * Without a stored claimableUntil there is nothing to derive a deadline from —\n * a caller who passed a bare token gets a bounded poll rather than a loop that\n * could outlive any claim window.\n */\nconst FALLBACK_POLL_WINDOW_MS = 24 * 60 * 60 * 1000;\n\nfunction resolveDeadline(claimableUntil: string | undefined, now: () => number): Date {\n const parsed = claimableUntil ? new Date(claimableUntil) : null;\n if (parsed && !Number.isNaN(parsed.getTime())) return parsed;\n return new Date(now() + FALLBACK_POLL_WINDOW_MS);\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport {\n saveCredential,\n saveFigmaToken,\n clearStorage,\n readCredentials,\n getCredentialsPath,\n extractTeamIdFromJWT,\n readPendingHandoff,\n type PendingHandoff,\n} from \"../auth/store.js\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { revokeStoredRefreshToken } from \"../auth/refresh.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printSuccess, printError, printKeyValue, printInfo } from \"../output/pretty.js\";\nimport { CliError } from \"../api/errors.js\";\n\nconst DEFAULT_API_URL = \"https://api.agentgrid.io\";\n\ntype PendingState = \"awaiting_claim\" | \"expired\";\n\nfunction describePendingHandoff(pending: PendingHandoff, state: PendingState) {\n return {\n state,\n sessionId: pending.sessionId,\n artifactUrl: pending.artifactUrl,\n claimableUntil: pending.claimableUntil,\n nextSteps:\n state === \"expired\"\n ? \"The claim window closed. Create another artifact, or ask your human for an agent invite: anima login --invite <url-or-code>\"\n : \"Send artifactUrl to your human, then run `anima login --handoff` to wait for the credentials their claim grants.\",\n };\n}\n\nfunction printPendingHandoff(pending: PendingHandoff, state: PendingState): void {\n console.log();\n if (state === \"expired\") {\n printInfo(`Anonymous artifact ${pending.sessionId} was never claimed — its window closed at ${pending.claimableUntil}.`);\n return;\n }\n printInfo(`Anonymous artifact ${pending.sessionId} is awaiting a claim (until ${pending.claimableUntil}):`);\n console.log(` ${chalk.cyan.underline(pending.artifactUrl)}`);\n console.log(` Run ${chalk.cyan(\"anima login --handoff\")} to wait for it.`);\n}\n\nexport const authCommand = new Command(\"auth\")\n .description(\"Manage authentication\")\n .option(\"--token <token>\", \"Store AgentGrid API token\")\n .option(\"--figma-token <token>\", \"Store Figma personal access token\")\n .option(\"--team-id <teamId>\", \"Team ID to associate with token\")\n .option(\"--status\", \"Show current auth status\")\n .option(\"--logout\", \"Clear stored credentials (alias for `anima logout`)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n\n try {\n if (opts.token || opts.figmaToken) {\n const toSave: { teamId?: string } = {};\n\n if (opts.token) {\n // A pasted token is a personal API token: full user authority, minted\n // outside any OAuth door, with nothing to renew.\n toSave.teamId = opts.teamId ?? extractTeamIdFromJWT(opts.token);\n saveCredential({ tokenType: \"account\", token: opts.token, teamId: toSave.teamId });\n }\n if (opts.figmaToken) {\n saveFigmaToken(opts.figmaToken);\n }\n\n if (mode === \"pretty\") {\n printSuccess(\"Credentials saved to \" + getCredentialsPath());\n if (opts.token) {\n printKeyValue(\"AgentGrid token\", \"saved\");\n if (toSave.teamId) printKeyValue(\"Team ID\", toSave.teamId);\n }\n if (opts.figmaToken) {\n printKeyValue(\"Figma token\", \"saved\");\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"token_saved\",\n path: getCredentialsPath(),\n ...(opts.token ? { teamId: toSave.teamId } : {}),\n ...(opts.figmaToken ? { figmaToken: true } : {}),\n });\n }\n return;\n }\n\n if (opts.logout) {\n const revoked = await revokeStoredRefreshToken(resolveApiUrl(opts.apiUrl));\n const deleted = clearStorage();\n if (mode === \"pretty\") {\n if (deleted) {\n printSuccess(\"Credentials cleared\");\n } else {\n printInfo(\"No stored credentials found\");\n }\n } else {\n outputResult(mode, { success: true, action: \"logged_out\", hadCredentials: deleted, revoked });\n }\n return;\n }\n\n if (opts.status) {\n // A handoff waiting to be claimed is reported alongside whatever\n // credential exists, and in place of one when there is none: \"has my\n // human claimed it yet?\" is asked precisely while not yet connected.\n const pending = readPendingHandoff();\n const pendingState = !pending\n ? undefined\n : new Date(pending.claimableUntil).getTime() <= Date.now()\n ? \"expired\"\n : \"awaiting_claim\";\n\n try {\n const auth = await resolveAuth(opts.apiUrl);\n const creds = readCredentials();\n const sourceName = auth.source === \"env\" ? \"ANIMA_API_TOKEN env var\" : getCredentialsPath();\n const hasFigma = !!(process.env.FIGMA_TOKEN || creds?.figmaToken);\n if (mode === \"pretty\") {\n printSuccess(\"Token configured\");\n printKeyValue(\"Source\", sourceName);\n printKeyValue(\"AgentGrid token\", auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4));\n printKeyValue(\"Token type\", auth.tokenType === \"agent\" ? \"agent (scoped, revocable)\" : \"account (personal API token)\");\n if (creds?.tokenType === \"agent\" && creds.expiresAt) printKeyValue(\"Expires\", creds.expiresAt);\n if (auth.teamId) printKeyValue(\"Team ID\", auth.teamId);\n printKeyValue(\"Figma token\", hasFigma ? \"configured\" : \"not set (needed for codegen/f2c)\");\n if (pending) printPendingHandoff(pending, pendingState!);\n } else {\n outputResult(mode, {\n success: true,\n source: auth.source,\n tokenType: auth.tokenType ?? \"account\",\n tokenPreview: auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4),\n teamId: auth.teamId,\n expiresAt: creds?.tokenType === \"agent\" ? creds.expiresAt : undefined,\n figmaToken: hasFigma,\n ...(pending ? { pendingHandoff: describePendingHandoff(pending, pendingState!) } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n // Not connected, but a claim is in flight: that is a state worth\n // reporting, not just the absence of a credential.\n if (pending && mode === \"pretty\") {\n printInfo(\"Not connected yet.\");\n printPendingHandoff(pending, pendingState!);\n } else if (pending) {\n outputResult(mode, {\n success: true,\n tokenType: null,\n pendingHandoff: describePendingHandoff(pending, pendingState!),\n });\n } else if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n } else {\n throw err;\n }\n }\n return;\n }\n\n // No flag: show help\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"Auth commands:\");\n console.log(` ${chalk.cyan(\"anima login\")} Log in (device flow — approve on any browser)`);\n console.log(` ${chalk.cyan(\"anima login --handoff\")} Wait for a human to claim your anonymous artifact`);\n console.log(` ${chalk.cyan(\"anima logout\")} Clear all credentials`);\n console.log(` ${chalk.cyan(\"anima auth --status\")} Check auth status`);\n console.log(` ${chalk.cyan(\"anima auth --figma-token <T>\")} Save Figma token (needed for codegen/f2c)`);\n console.log();\n console.log(` Figma token: ${chalk.cyan.underline(\"https://www.figma.com\")} > Settings > Personal access tokens`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n message: \"Run `anima login`, or use --status / --logout / --figma-token\",\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { clearStorage, getCredentialsPath } from \"../auth/store.js\";\nimport { revokeStoredRefreshToken } from \"../auth/refresh.js\";\nimport { deleteConfig, resolveApiUrl } from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { printSuccess, printInfo } from \"../output/pretty.js\";\n\n/**\n * `anima logout` — clear all stored credentials from this machine. Removes the\n * credentials file (Anima token, Figma token, agent metadata) and the config\n * directory, and revokes the agent credentials server-side so a copy taken from\n * this machine stops working.\n */\nexport const logoutCommand = new Command(\"logout\")\n .description(\"Clear all stored credentials (AgentGrid + Figma tokens) from this machine\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n // Revoke before clearing: this kills every credential descended from the\n // same consent, so a copy of the token taken from this machine stops\n // working too.\n const revoked = await revokeStoredRefreshToken(resolveApiUrl(opts.apiUrl));\n const hadCredentials = clearStorage();\n // Full machine reset: logout removes stored config too (e.g. the api-url\n // persisted by `login --invite`), so the machine is pristine afterwards.\n deleteConfig();\n\n if (mode === \"pretty\") {\n if (hadCredentials) {\n printSuccess(\"Logged out — all credentials cleared from \" + getCredentialsPath());\n if (revoked) printInfo(\"Agent credentials revoked server-side\");\n } else {\n printInfo(\"No stored credentials found\");\n }\n } else {\n outputResult(mode, { success: true, action: \"logged_out\", hadCredentials, revoked });\n }\n });\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printError } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError, apiError } from \"../api/errors.js\";\n\ntype UnpublishResult = {\n success: boolean;\n message?: string;\n error?: string;\n reason?: string;\n};\n\n/** Mirror of the `artifact-unpublish` MCP tool — the inverse of `publish`. */\nexport const unpublishCommand = new Command(\"unpublish\")\n .description(\"Take a published artifact offline (clears its live URL; code and artifact stay intact)\")\n .argument(\"<sessionId>\", \"Session ID of the published artifact\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (sessionId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const auth = await resolveAuth(opts.apiUrl);\n progress.start(\"Unpublishing...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<UnpublishResult>(\"artifact-unpublish\", { sessionId })\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Unpublish failed\", result);\n }\n\n progress.succeed(\"Unpublished\");\n if (mode === \"pretty\") {\n printSuccess(result.message || `Artifact ${sessionId} is no longer publicly reachable.`);\n } else {\n outputResult(mode, { success: true, sessionId, ...(result.message ? { message: result.message } : {}) });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printError } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError, apiError, validationError } from \"../api/errors.js\";\n\ntype UpdateResult = {\n success: boolean;\n message?: string;\n error?: string;\n reason?: string;\n};\n\n/**\n * Mirror of the `artifact-update_metadata` MCP tool — metadata only (name,\n * visibility); it never touches code or content (that is the git flow).\n */\nexport const updateCommand = new Command(\"update\")\n .description(\"Update an artifact's metadata: display name and/or visibility (never touches code)\")\n .argument(\"<sessionId>\", \"Session ID of the artifact\")\n .option(\"--name <name>\", \"New display name\")\n .option(\"--privacy <privacy>\", \"public (anyone with the link) | private (team only)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (sessionId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n if (!opts.name && !opts.privacy) {\n throw validationError(\"Nothing to update — pass --name and/or --privacy\");\n }\n if (opts.privacy && ![\"public\", \"private\"].includes(opts.privacy)) {\n throw validationError(`Invalid privacy \"${opts.privacy}\". Must be public or private.`);\n }\n\n const auth = await resolveAuth(opts.apiUrl);\n progress.start(\"Updating...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n client.callTool<UpdateResult>(\"artifact-update_metadata\", {\n sessionId,\n ...(opts.name ? { name: opts.name } : {}),\n ...(opts.privacy ? { privacy: opts.privacy } : {}),\n })\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Update failed\", result);\n }\n\n progress.succeed(\"Updated\");\n if (mode === \"pretty\") {\n printSuccess(result.message || `Artifact ${sessionId} updated.`);\n } else {\n outputResult(mode, { success: true, sessionId, ...(result.message ? { message: result.message } : {}) });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport {\n readConfig,\n setConfig,\n unsetConfig,\n getConfigPath,\n isConfigKey,\n configKeys,\n CONFIG_KEYS,\n resolveApiUrl,\n DEFAULT_API_URL,\n type ConfigKey,\n} from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { printSuccess, printInfo, printKeyValue } from \"../output/pretty.js\";\nimport { validationError } from \"../api/errors.js\";\n\n/**\n * `anima config` — store non-secret CLI preferences in\n * ~/.config/anima/config.json so you don't have to pass flags like `--api-url`\n * every time. Resolution precedence for the API URL: flag → ANIMA_API_URL env →\n * stored config → default.\n *\n * anima config set api-url http://localhost:3789\n * anima config get api-url\n * anima config list\n * anima config unset api-url\n */\nexport const configCommand = new Command(\"config\").description(\n `Store CLI preferences (keys: ${configKeys().join(\", \")})`\n);\n\nconfigCommand\n .command(\"set <key> <value>\")\n .description(\"Set a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, value: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n if (key === \"api-url\") assertUrl(value);\n setConfig(key, value);\n\n if (mode === \"pretty\") printSuccess(`Set ${key} = ${value}`);\n else outputResult(mode, { success: true, action: \"config_set\", key, value });\n });\n\nconfigCommand\n .command(\"get <key>\")\n .description(\"Print a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const value = readConfig()[CONFIG_KEYS[key]];\n\n if (mode === \"pretty\") {\n if (value) console.log(value);\n else printInfo(`${key} is not set`);\n } else {\n outputResult(mode, { success: true, key, value: value ?? null });\n }\n });\n\nconfigCommand\n .command(\"list\")\n .alias(\"ls\")\n .description(\"Show all config values and where the API URL resolves from\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const mode = detectOutputMode(opts);\n const config = readConfig();\n const resolvedApiUrl = resolveApiUrl();\n\n if (mode === \"pretty\") {\n printInfo(\"Config: \" + getConfigPath());\n printKeyValue(\"api-url\", config.apiUrl ?? `(default) ${DEFAULT_API_URL}`);\n if (process.env.ANIMA_API_URL) {\n printInfo(`ANIMA_API_URL env is set — it overrides config (effective: ${resolvedApiUrl})`);\n }\n } else {\n outputResult(mode, {\n success: true,\n path: getConfigPath(),\n config,\n resolved: { apiUrl: resolvedApiUrl },\n });\n }\n });\n\nconfigCommand\n .command(\"unset <key>\")\n .description(\"Remove a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const removed = unsetConfig(key);\n\n if (mode === \"pretty\") {\n if (removed) printSuccess(`Unset ${key}`);\n else printInfo(`${key} was not set`);\n } else {\n outputResult(mode, { success: true, action: \"config_unset\", key, removed });\n }\n });\n\nfunction assertKey(key: string): asserts key is ConfigKey {\n if (!isConfigKey(key)) {\n throw validationError(`Unknown config key \"${key}\". Valid keys: ${configKeys().join(\", \")}`);\n }\n}\n\nfunction assertUrl(value: string): void {\n try {\n new URL(value);\n } catch {\n throw validationError(`\"${value}\" is not a valid URL`);\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputError, outputResult } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printError, printKeyValue, printSuccess } from \"../output/pretty.js\";\nimport { parsePlaygroundUrl } from \"../utils/playgroundUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError, validationError } from \"../api/errors.js\";\n\ntype DuplicateSuccess = {\n success: true;\n sessionId: string;\n sourceSessionId: string;\n name: string;\n playgroundUrl: string;\n previewUrl: string;\n nextSteps: string;\n};\n\ntype DuplicateFailure = {\n success: false;\n code?: string;\n error?: string;\n reason?: string;\n};\n\ntype DuplicateResult = DuplicateSuccess | DuplicateFailure;\n\n/** Exact input accepted by the artifact-duplicate MCP tool. */\nexport function buildDuplicateArgs(\n artifactUrl: string,\n name?: string\n): { sessionId: string; name?: string } {\n const sessionId = parsePlaygroundUrl(artifactUrl);\n if (!sessionId) {\n throw validationError(\"A source artifact URL or session ID is required\");\n }\n if (name !== undefined && (name.length === 0 || name.length > 120)) {\n throw validationError(\"--name must be between 1 and 120 characters\");\n }\n return { sessionId, ...(name !== undefined ? { name } : {}) };\n}\n\nexport function createDuplicateCommand(): Command {\n return new Command(\"duplicate\")\n .description(\n \"Duplicate an artifact into a new, independent artifact. Copies code, assets, and supported database content; chat and custom domains are not copied. Duplication is non-idempotent: if a request times out or its response is lost, list recent artifacts before retrying because the first request may already have created the copy.\"\n )\n .argument(\"<artifactUrl>\", \"Source artifact URL or session ID\")\n .option(\"--name <name>\", \"Display name for the duplicate (defaults to '<source name> (Copy)')\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const args = buildDuplicateArgs(artifactUrl, opts.name);\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(\"Duplicating artifact...\");\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<DuplicateResult>(\"artifact-duplicate\", args)\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Artifact duplication failed\", result);\n }\n\n progress.succeed(\"Artifact duplicated\");\n if (mode === \"pretty\") {\n console.log();\n printSuccess(\"Artifact duplicated successfully!\");\n printKeyValue(\"Name\", result.name);\n printKeyValue(\"Session ID\", result.sessionId);\n printKeyValue(\"Source session\", result.sourceSessionId);\n printKeyValue(\"Artifact\", chalk.cyan.underline(result.playgroundUrl));\n printKeyValue(\"Preview\", chalk.cyan.underline(result.previewUrl));\n printKeyValue(\"Next steps\", result.nextSteps);\n console.log();\n } else {\n outputResult(mode, result);\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n}\n\nexport const duplicateCommand = createDuplicateCommand();\n"],"mappings":"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","names":["Command","chalk","required","fs","path","fs","path","os","CONFIG_DIR","path","chalk","Command","chalk","Command","chalk","relative","Command","Command","Command","fs","path","Command","Command","chalk","Command","chalk","Command","Command","chalk","defaultSleep","Command","apiUrl","chalk","Command","Command","chalk","DEFAULT_API_URL","chalk","Command","Command","Command","Command","Command","Command","Command","Command","Command","Command","chalk","Command","chalk","Command"]}