@animaapp/cli 0.8.0 → 0.9.0

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/artifactUrl.ts","../src/utils/waitForArtifact.ts","../src/api/anonymousCreate.ts","../src/commands/list.ts","../src/commands/status.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","../src/commands/explore.ts","../src/api/tool.ts","../src/commands/runner.ts","../src/commands/edit.ts","../src/commands/uploadAsset.ts","../src/commands/delete.ts","../src/commands/review.ts","../src/commands/skill.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createCommand } from \"./commands/create.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { statusCommand } from \"./commands/status.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 { exploreCommand } from \"./commands/explore.js\";\nimport { editCommand } from \"./commands/edit.js\";\nimport { uploadAssetCommand } from \"./commands/uploadAsset.js\";\nimport { deleteCommand } from \"./commands/delete.js\";\nimport { reviewCommand } from \"./commands/review.js\";\nimport { skillCommand } from \"./commands/skill.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 — create, change, publish and share artifacts on AgentGrid.\nAn artifact is a real git repository, and every command below runs one\nAgentGrid MCP tool for you. The command list is at the bottom; run\n\"anima <command> --help\" for a command's own options.\n\nTHE MAIN FLOW (build something and put it on AgentGrid):\n 1. anima login # once; a human approves\n 2. anima 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. Change it. Two doors, same git repository:\n - no clone: \"explore\" to read the files, \"edit\" to commit them. Needs no\n shell, no git binary and no network of its own — prefer it.\n - a real checkout: \"get-git-token\" (create already returns one), then\n git clone / commit / push. Worth it for a large refactor, running the\n project, branches or rewriting history.\n 4. Share the artifactUrl — app.agentgrid.io/artifacts/<sessionId>. That IS\n sharing: the artifact is already visible there. Do NOT run \"publish\"\n unless a human explicitly asked for a public site; offer it as a\n follow-up question instead.\n\nTIMING — how long the COMMAND blocks, not how long the server takes:\n create -t p2c|l2c|f2c BLOCKS 3-7 min. The generation itself is\n asynchronous, but create waits it out for you, so\n what it prints is a finished app and a failed\n generation exits non-zero. Keep the default\n 600000ms --timeout. Pass --no-wait to get the\n sessionId back in seconds and do the waiting\n yourself with \"anima status <sessionId> --wait\".\n publish / unpublish BLOCKS 1-3 min\n everything else seconds, create -t empty|import included\n\nAUTHENTICATION:\n anima skill <path> # install this guide where your runtime reads skills\n anima login # device flow — a human approves on any device\n anima login --invite <url> # redeem a pre-approved invite (no approval step)\n anima create --anonymous … # no account at all; hand off to a human later\n Credentials live in ~/.config/anima/; \"logout\" removes everything.\n\nEXAMPLES:\n anima create -t import --from ./my-project\n anima status <sessionId> --wait\n anima explore <sessionId> --search \"buttonColor\"\n anima edit <sessionId> -m \"Blue pill\" --replace src/App.tsx --old red --new blue\n anima review list # what humans asked you to change\n anima publish <sessionId> # only on explicit request\n\nOUTPUT: pretty text in a terminal; a single JSON object on stdout when piped\n or given --json. Progress and prompts go to stderr, so stdout stays clean.\n Add --verbose to stream progress in JSON mode.`\n )\n .version(version, \"-v, --version\");\n\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\nprogram.addCommand(listCommand);\nprogram.addCommand(createCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(exploreCommand);\nprogram.addCommand(editCommand);\nprogram.addCommand(uploadAssetCommand);\nprogram.addCommand(getGitTokenCommand);\nprogram.addCommand(reviewCommand);\nprogram.addCommand(duplicateCommand);\nprogram.addCommand(publishCommand);\nprogram.addCommand(unpublishCommand);\nprogram.addCommand(updateCommand);\nprogram.addCommand(deleteCommand);\nprogram.addCommand(codegenCommand);\nprogram.addCommand(skillCommand);\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 { artifactUrlFor } from \"../utils/artifactUrl.js\";\nimport { waitForArtifact } from \"../utils/waitForArtifact.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 /** 'generating' for p2c/l2c/f2c: the job runs in the background. */\n status?: \"generating\";\n /** The artifact's page in Agent Grid — the link to share. */\n artifactUrl?: string;\n /** App artifacts only: the Playground editor and the rendered preview. */\n playgroundUrl?: string;\n previewUrl?: 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 .summary(\"Create an artifact: your code, an empty repo, or AI generation\")\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(\n \"--no-wait\",\n \"Return as soon as generation starts (p2c/l2c/f2c), instead of waiting for the finished app. Poll with `anima status <sessionId> --wait`\"\n )\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 timeoutMs = parseInt(opts.timeout, 10);\n const deadline = Date.now() + timeoutMs;\n\n const { result, settled } = await withMcp(mcpConfig, async (client) => {\n const created = await client.callTool<CreateResult>(\"artifact-create\", args, { timeoutMs });\n if (!created.success || !created.sessionId) return { created };\n\n // p2c/l2c/f2c are asynchronous: artifact-create returns the moment the\n // job is enqueued. Without this wait the command would report success\n // and hand over a link for an app that is still being built.\n if (created.status !== \"generating\" || !opts.wait) return { created };\n\n progress.update(\"Generating your app...\");\n const status = await waitForArtifact(client, created.sessionId, {\n deadline,\n onProgress: (message) => progress.update(message),\n });\n return { created, status };\n }).then(({ created, status }) => ({ result: created, settled: status }));\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 if (settled?.status === \"failed\") {\n throw apiError(settled.error || \"Generation failed\", settled);\n }\n\n // The settled status carries the final URLs. While a job is in flight\n // `playgroundUrl` is the /loading page, not the editor, so prefer what\n // the finished status returned whenever there is one.\n const artifactUrl = settled?.artifactUrl || result.artifactUrl || artifactUrlFor(result.sessionId);\n const playgroundUrl = settled?.playgroundUrl ?? result.playgroundUrl;\n const previewUrl = settled?.previewUrl ?? result.previewUrl;\n const status = settled?.status ?? result.status ?? \"ready\";\n\n progress.succeed(settled ? \"Your app is ready!\" : \"Artifact created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({\n sessionId: result.sessionId,\n artifactUrl,\n playgroundUrl,\n });\n if (status === \"generating\") {\n console.log(\n ` Still generating. Wait for it with ${chalk.cyan(`anima status ${result.sessionId} --wait`)}.`\n );\n console.log();\n }\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 status,\n artifactUrl,\n ...(playgroundUrl ? { playgroundUrl } : {}),\n ...(previewUrl ? { previewUrl } : {}),\n ...(settled?.name ? { name: settled.name } : {}),\n ...(status === \"generating\"\n ? {\n nextSteps: `Generation is still running. Wait for it with: anima status ${result.sessionId} --wait`,\n }\n : {}),\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\n/**\n * `artifactUrl` is the artifact's page in Agent Grid and the link to share.\n * `playgroundUrl` is the editor and exists only for `app` artifacts, so it is\n * shown beside that link rather than in place of it.\n */\nexport function printSessionResult(result: {\n sessionId: string;\n artifactUrl?: 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.artifactUrl) {\n printKeyValue(\"Your artifact\", chalk.cyan.underline(result.artifactUrl));\n }\n if (result.playgroundUrl) {\n printKeyValue(\"Edit in Playground\", 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","/**\n * An artifact's page in Agent Grid — `artifactUrl` in every MCP tool result,\n * and the link to hand a human. The Playground host (`playgroundUrl` to edit,\n * `previewUrl` to render) answers only for `app` artifacts, so it is never the\n * link to fall back on.\n */\nexport const ARTIFACT_BASE = \"https://app.agentgrid.io/artifacts\";\n\n/** The artifact page for a session, for results that predate `artifactUrl`. */\nexport function artifactUrlFor(sessionId: string): string {\n return `${ARTIFACT_BASE}/${sessionId}`;\n}\n\n/**\n * Parse an artifact reference to its session ID.\n * Supported formats:\n * - https://app.agentgrid.io/artifacts/SESSION_ID\n * - https://dev.animaapp.com/chat/SESSION_ID (the Playground host)\n * - Just a session ID string\n */\nexport function parseArtifactUrl(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: /artifacts/SESSION_ID or /chat/SESSION_ID — the session id is\n // the segment after either marker.\n const markerIndex = parts.findIndex((p) => p === \"artifacts\" || p === \"chat\");\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 type { AnimaMcpClient } from \"../api/mcp.js\";\nimport { CliError, EXIT_CODES } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * `artifact-status` — the only way to learn that a generation finished.\n *\n * `artifact-create` no longer blocks: p2c/l2c/f2c return immediately with\n * `status: 'generating'` while the job runs in the background. A `wait: true`\n * status call blocks server-side for about 45 seconds and comes back still\n * generating if the job outlives that, so the waiting is a loop of those calls.\n */\n\nexport type ArtifactStatusResult = {\n success: boolean;\n sessionId?: string;\n status?: \"generating\" | \"ready\" | \"failed\";\n /** 0–100, while generating. */\n progress?: number;\n name?: string;\n thumbnailUrl?: string;\n artifactType?: \"app\" | \"markdown\" | \"asset\";\n /** Absent while failed — a failed job has no page to open. */\n artifactUrl?: string;\n playgroundUrl?: string;\n previewUrl?: string;\n /** Failure reason, when status is 'failed'. */\n error?: string;\n reason?: string;\n nextStep?: string;\n};\n\n/** Room for the server's ~45s wait plus the round trip. Progress resets it. */\nconst STATUS_CALL_TIMEOUT_MS = 120_000;\n\nexport async function fetchArtifactStatus(\n client: AnimaMcpClient,\n sessionId: string,\n options: { wait?: boolean; onProgress?: (message: string) => void } = {}\n): Promise<ArtifactStatusResult> {\n return client.callTool<ArtifactStatusResult>(\n \"artifact-status\",\n { sessionId, wait: options.wait ?? false },\n {\n timeoutMs: STATUS_CALL_TIMEOUT_MS,\n onProgress: options.onProgress\n ? (p) => options.onProgress!(p.message ?? `Generating (${Math.round(p.progress * 100)}%)...`)\n : undefined,\n }\n );\n}\n\n/**\n * Poll until the artifact is ready or failed. Returns the terminal status;\n * throws TIMEOUT if `deadline` passes while it is still generating — the job\n * itself keeps running, so the message says how to pick the wait back up.\n */\nexport async function waitForArtifact(\n client: AnimaMcpClient,\n sessionId: string,\n options: { deadline: number; onProgress?: (message: string) => void } = { deadline: Date.now() }\n): Promise<ArtifactStatusResult> {\n for (;;) {\n const result = await fetchArtifactStatus(client, sessionId, {\n wait: true,\n onProgress: options.onProgress,\n });\n\n if (!result.success) {\n throw new CliError(\n \"API_ERROR\",\n result.reason || result.error || \"Could not read the artifact's status\",\n EXIT_CODES.API_ERROR,\n result\n );\n }\n if (result.status !== \"generating\") {\n logEvent(\"generation_settled\", { sessionId, status: result.status });\n return result;\n }\n\n // Still generating. The next call blocks server-side for another ~45s, so\n // starting one past the deadline would overshoot it by that much.\n if (Date.now() >= options.deadline) {\n logEvent(\"generation_wait_timeout\", { sessionId, progress: result.progress });\n throw generationTimeoutError(sessionId, result.progress);\n }\n options.onProgress?.(\n result.progress !== undefined ? `Generating (${result.progress}%)...` : \"Generating...\"\n );\n }\n}\n\nfunction generationTimeoutError(sessionId: string, progress?: number): CliError {\n const reached = progress !== undefined ? ` (reached ${progress}%)` : \"\";\n return new CliError(\n \"TIMEOUT\",\n `Still generating${reached} when the wait budget ran out. Generation is NOT cancelled — it ` +\n `keeps running in the background.\\n` +\n `Pick the wait back up with: anima status ${sessionId} --wait\\n` +\n `Or allow longer next time with --timeout <ms>.`,\n EXIT_CODES.TIMEOUT,\n { sessionId, progress }\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 { artifactUrlFor } from \"../utils/artifactUrl.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 .summary(\"List your team's artifacts, most-recently-updated first\")\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(` ${chalk.cyan.underline(artifactUrlFor(a.sessionId))}`);\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 // The listing tool returns no URL; deriving it here saves every caller\n // the same string concatenation, and keeps one definition of the link.\n artifacts: artifacts.map((a) => ({\n ...a,\n ...(a.sessionId ? { artifactUrl: artifactUrlFor(a.sessionId) } : {}),\n })),\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 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 { printSuccess, printError, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { fetchArtifactStatus, waitForArtifact } from \"../utils/waitForArtifact.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `artifact-status` MCP tool. Generation (p2c/l2c/f2c) is\n * asynchronous, so this is how a caller learns it finished — `create` waits by\n * default, and this command picks that wait back up or takes a snapshot.\n */\nexport const statusCommand = new Command(\"status\")\n .summary(\"Check whether an artifact finished generating\")\n .description(\n \"Check whether an artifact finished generating. --wait blocks until it is ready or failed.\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .option(\"--wait\", \"Block until generation finishes instead of returning a snapshot\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"How long --wait may block\", \"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 (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 = parseArtifactUrl(artifactUrl);\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(opts.wait ? \"Waiting for generation...\" : \"Checking status...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n opts.wait\n ? waitForArtifact(client, sessionId, {\n deadline: Date.now() + parseInt(opts.timeout, 10),\n onProgress: (message) => progress.update(message),\n })\n : fetchArtifactStatus(client, sessionId)\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Could not read the artifact's status\", result);\n }\n\n progress.succeed(`Status: ${result.status}`);\n\n if (mode === \"pretty\") {\n printArtifactStatus(sessionId, result);\n } else {\n outputResult(mode, { ...result, sessionId: result.sessionId ?? sessionId });\n }\n\n // A failed generation is a failed command: an agent that only checks the\n // exit code must not read \"failed\" as \"done\".\n if (result.status === \"failed\") {\n process.exit(1);\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\nfunction printArtifactStatus(\n sessionId: string,\n result: Awaited<ReturnType<typeof fetchArtifactStatus>>\n): void {\n console.log();\n if (result.status === \"ready\") {\n printSuccess(\"Ready!\");\n } else if (result.status === \"failed\") {\n printError(`Generation failed: ${result.error ?? \"no reason given\"}`);\n }\n printKeyValue(\"Session ID\", result.sessionId ?? sessionId);\n printKeyValue(\"Status\", result.status ?? \"unknown\");\n if (result.name) printKeyValue(\"Name\", result.name);\n if (result.status === \"generating\" && result.progress !== undefined) {\n printKeyValue(\"Progress\", `${result.progress}%`);\n }\n if (result.artifactUrl) {\n printKeyValue(\"Your artifact\", chalk.cyan.underline(result.artifactUrl));\n }\n if (result.playgroundUrl) {\n printKeyValue(\"Edit in Playground\", chalk.cyan.underline(result.playgroundUrl));\n }\n if (result.nextStep) {\n console.log();\n console.log(` Still generating — run this again with --wait to keep waiting.`);\n }\n console.log();\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 .summary(\"Deploy to a public live URL (only when asked)\")\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 .summary(\"Convert a Figma design to local code files\")\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 { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { gitConfigCommands, 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 .summary(\"Mint git access to an artifact's repository\")\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 = parseArtifactUrl(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 // A clone has no identity of its own: without this the push is\n // attributed to whatever git identity this machine happens to carry.\n if (grant.commitAuthor) {\n console.log(\" In the clone, set who your commits are from:\");\n console.log(` ${chalk.cyan(gitConfigCommands(grant.commitAuthor))}`);\n console.log();\n }\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 ...(grant.commitAuthor\n ? {\n commitAuthor: grant.commitAuthor,\n gitConfigCommand: gitConfigCommands(grant.commitAuthor),\n }\n : {}),\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,\n * commitAuthor }` on a grant, or `{ success: false, error, reason }` on a\n * denial. The MCP client (api/mcp.ts) already JSON-parses tool text, so this\n * receives the parsed object — a string only arrives if that parse failed. The\n * clone URL embeds a 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 * Who the server attributes commits from this clone to — the authenticated\n * agent, or the human behind the credential. A clone carries no identity of\n * its own, so without applying this a push is attributed to whatever local\n * git identity the machine happens to have.\n */\n commitAuthor?: { name: string; email: 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 commitAuthor?: { name?: unknown; email?: unknown };\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 ...(commitAuthorOf(body.commitAuthor) ? { commitAuthor: commitAuthorOf(body.commitAuthor)! } : {}),\n };\n}\n\n/** Both halves or neither: a half-configured identity is worse than none. */\nfunction commitAuthorOf(value: { name?: unknown; email?: unknown } | undefined) {\n if (!value || typeof value.name !== \"string\" || typeof value.email !== \"string\") return undefined;\n if (!value.name || !value.email) return undefined;\n return { name: value.name, email: value.email };\n}\n\n/** Single-quote for a POSIX shell, so a name with an apostrophe still pastes. */\nexport function shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\n/** The commands that put the grant's identity on a fresh clone. */\nexport function gitConfigCommands(commitAuthor: { name: string; email: string }): string {\n return `git config user.name ${shellQuote(commitAuthor.name)} && git config user.email ${shellQuote(commitAuthor.email)}`;\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 .summary(\"Print an MCP server config for your MCP client\")\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 .summary(\"Connect this machine as a scoped agent identity\")\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 .summary(\"Inspect or manage stored credentials\")\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 .summary(\"Disconnect: revoke and clear every stored credential\")\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 .summary(\"Take a published artifact offline\")\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 .summary(\"Rename an artifact or change its visibility\")\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\")\n .summary(\"Store CLI preferences (e.g. a default API URL)\").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 { parseArtifactUrl } from \"../utils/artifactUrl.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 artifactType?: \"app\" | \"markdown\" | \"asset\";\n artifactUrl: string;\n // App copies only — a markdown or asset artifact has no Playground session.\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 = parseArtifactUrl(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 .summary(\"Copy an artifact into a new, independent one\")\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.artifactUrl));\n if (result.playgroundUrl) {\n printKeyValue(\"Edit in Playground\", chalk.cyan.underline(result.playgroundUrl));\n }\n if (result.previewUrl) {\n printKeyValue(\"Preview\", chalk.cyan.underline(result.previewUrl));\n }\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","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { runTool } from \"../api/tool.js\";\nimport { validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `artifact-explore` MCP tool — read an artifact's files without\n * git, a shell or a clone. `revision` comes back on every response and is what\n * `anima edit --base-revision` expects.\n */\n\ntype ReadFile = {\n path: string;\n content?: string;\n totalLines?: number;\n startLine?: number;\n endLine?: number;\n truncated?: boolean;\n eol?: \"lf\" | \"crlf\";\n /** The bytes are not text, so metadata stands in for content. */\n asset?: boolean;\n size?: number;\n mime?: string;\n deferred?: boolean;\n};\n\ntype SearchMatch = { path: string; line: number; lineText: string; occurrences: number };\n\ntype CommitSummary = { revision: string; message: string; author: string; date: string };\n\ntype ExploreResult = {\n success: boolean;\n revision?: string;\n // tree\n files?: string[] | ReadFile[];\n unwritable?: Record<string, \"symlink\" | \"submodule\">;\n matchedFiles?: number;\n truncated?: boolean;\n // read\n readAt?: string;\n missingPaths?: string[];\n suggestions?: Record<string, string[]>;\n // search\n matches?: SearchMatch[];\n notSearched?: { assets?: number; excluded?: number };\n // history\n commits?: CommitSummary[];\n commit?: CommitSummary & { changedFiles?: Array<{ path: string; change: string }> };\n nextCursor?: string | null;\n};\n\nexport const exploreCommand = new Command(\"explore\")\n .summary(\"Read an artifact's files: list, search, read, history\")\n .description(\n \"Inspect an artifact's files without git: list them (--tree), search them (--search), read them (--read), or show commits (--history).\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .option(\"--tree\", \"List file paths\")\n .option(\"--search <query>\", \"Find text inside files — start here when you don't know the file\")\n .option(\"--read <paths...>\", \"Return the contents of these files\")\n .option(\"--history\", \"List commits, newest first\")\n .option(\"--path <prefix>\", \"tree/search: a literal directory prefix (not a glob)\")\n .option(\"--range <start,end>\", \"read: line window, 1-based inclusive, for a single file\")\n .option(\"--revision <rev>\", \"Look at the artifact as it was at this commit\")\n .option(\"--regex\", \"search: treat the query as a JavaScript regular expression\")\n .option(\"--case-sensitive\", \"search: match case exactly\")\n .option(\"--include-excluded\", \"tree/search: also look inside node_modules, dist and build\")\n .option(\"--limit <n>\", \"tree/search/history: maximum rows to return\")\n .option(\"--cursor <cursor>\", \"history: continue after a previous response's nextCursor\")\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 (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const sessionId = parseArtifactUrl(artifactUrl);\n const args = buildExploreArgs(sessionId, opts);\n\n const result = await runTool<ExploreResult>(\"artifact-explore\", args, { apiUrl: opts.apiUrl });\n\n if (mode === \"pretty\") {\n printExplore(args.action as string, result);\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nexport function buildExploreArgs(sessionId: string, opts: Record<string, unknown>): Record<string, unknown> {\n const chosen = [\n opts.tree ? \"tree\" : null,\n opts.search ? \"search\" : null,\n opts.read ? \"read\" : null,\n opts.history ? \"history\" : null,\n ].filter(Boolean) as string[];\n\n if (chosen.length !== 1) {\n throw validationError(\n \"Pass exactly one of --tree, --search <query>, --read <paths...> or --history. \" +\n \"Not sure which file to change? Start with --search.\"\n );\n }\n const action = chosen[0];\n\n const args: Record<string, unknown> = { sessionId, action };\n if (opts.revision) args.revision = opts.revision;\n if (opts.limit !== undefined) args.limit = parseLimit(opts.limit as string);\n\n switch (action) {\n case \"tree\":\n if (opts.path) args.path = opts.path;\n if (opts.includeExcluded) args.includeExcluded = true;\n break;\n case \"search\":\n args.query = opts.search;\n if (opts.path) args.path = opts.path;\n if (opts.regex) args.regex = true;\n if (opts.caseSensitive) args.caseSensitive = true;\n if (opts.includeExcluded) args.includeExcluded = true;\n break;\n case \"read\": {\n const paths = opts.read as string[];\n args.paths = paths;\n if (opts.range) {\n if (paths.length !== 1) {\n throw validationError(\"--range applies to a single file; pass one path to --read.\");\n }\n args.range = opts.range;\n }\n break;\n }\n case \"history\":\n if (opts.cursor) args.cursor = opts.cursor;\n break;\n }\n\n return args;\n}\n\nfunction parseLimit(value: string): number {\n const limit = Number(value);\n if (!Number.isInteger(limit) || limit < 1) {\n throw validationError(`--limit must be a positive whole number (got \"${value}\").`);\n }\n return limit;\n}\n\nfunction printExplore(action: string, result: ExploreResult): void {\n console.log();\n\n if (action === \"tree\") {\n for (const file of (result.files ?? []) as string[]) {\n const kind = result.unwritable?.[file];\n console.log(` ${file}${kind ? chalk.gray(` (${kind} — git only)`) : \"\"}`);\n }\n if (result.matchedFiles !== undefined) {\n console.log();\n console.log(chalk.gray(` ${(result.files ?? []).length} of ${result.matchedFiles} shown`));\n }\n } else if (action === \"search\") {\n for (const match of result.matches ?? []) {\n console.log(` ${chalk.cyan(match.path)}:${match.line} ${match.lineText.trim()}`);\n }\n if (!result.matches?.length) {\n console.log(\" No matches.\");\n const skipped = result.notSearched;\n if (skipped?.excluded) {\n console.log(\n chalk.yellow(\n ` ${skipped.excluded} files were skipped (node_modules, dist, build) — retry with --include-excluded.`\n )\n );\n }\n if (skipped?.assets) {\n console.log(chalk.gray(` ${skipped.assets} binary files cannot match a text query.`));\n }\n }\n } else if (action === \"read\") {\n for (const file of (result.files ?? []) as ReadFile[]) {\n console.log(chalk.bold(` ${file.path}`));\n if (file.asset) {\n console.log(chalk.gray(` binary — ${file.size ?? \"?\"} bytes, ${file.mime ?? \"unknown type\"}`));\n } else if (file.deferred) {\n console.log(chalk.yellow(\" not returned: the response ran out of budget — read it on its own\"));\n } else {\n console.log(file.content ?? \"\");\n if (file.truncated) {\n console.log(\n chalk.yellow(\n ` lines ${file.startLine}-${file.endLine} of ${file.totalLines} — read the rest with --range`\n )\n );\n }\n }\n console.log();\n }\n for (const missing of result.missingPaths ?? []) {\n const near = result.suggestions?.[missing];\n console.log(chalk.yellow(` Not found: ${missing}${near?.length ? ` — did you mean ${near.join(\", \")}?` : \"\"}`));\n }\n } else {\n const commits = result.commit ? [result.commit] : (result.commits ?? []);\n for (const commit of commits) {\n console.log(` ${chalk.yellow(commit.revision.slice(0, 10))} ${commit.message.split(\"\\n\")[0]}`);\n console.log(chalk.gray(` ${commit.author} — ${commit.date}`));\n }\n for (const changed of result.commit?.changedFiles ?? []) {\n console.log(chalk.gray(` ${changed.change.padEnd(8)} ${changed.path}`));\n }\n }\n\n if (result.truncated) {\n console.log(chalk.yellow(\" The list was capped — raise --limit to see more.\"));\n }\n if (result.revision) {\n console.log();\n console.log(chalk.gray(` revision: ${result.revision} (pass to \\`anima edit --base-revision\\`)`));\n }\n console.log();\n}\n","import { resolveAuth } from \"../auth/token.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { withMcp, type CallToolOptions } from \"./mcp.js\";\nimport { apiError } from \"./errors.js\";\n\n/**\n * Resolve credentials, run one MCP tool, and turn a `{ success: false }`\n * payload into a CliError. Tools report failure in the result rather than as a\n * transport error, and they use two shapes for it: most carry `error` as a\n * string beside `reason`, while the artifact-content tools nest\n * `{ code, message, retryable }`. Both land here so no command has to know.\n */\nexport type ToolFailure = {\n success?: boolean;\n error?: string | { code?: string; message?: string; retryable?: boolean; details?: unknown };\n reason?: string;\n nextSteps?: string | string[];\n};\n\nexport type RunToolOptions = {\n apiUrl?: string;\n figmaToken?: string;\n call?: CallToolOptions;\n};\n\nexport async function runTool<T extends ToolFailure>(\n toolName: string,\n args: Record<string, unknown>,\n options: RunToolOptions = {}\n): Promise<T> {\n const auth = await resolveAuth(options.apiUrl);\n const result = await withMcp(\n {\n apiBaseUrl: resolveApiUrl(options.apiUrl),\n token: auth.token,\n teamId: auth.teamId,\n ...(options.figmaToken ? { figmaToken: options.figmaToken } : {}),\n },\n (client) => client.callTool<T>(toolName, args, options.call)\n );\n\n if (result.success === false) {\n throw apiError(describeFailure(result), result);\n }\n return result;\n}\n\nfunction describeFailure(result: ToolFailure): string {\n const base =\n typeof result.error === \"object\" && result.error\n ? result.error.message || result.error.code || \"The tool reported a failure\"\n : result.reason || result.error || \"The tool reported a failure\";\n\n const nextSteps = Array.isArray(result.nextSteps) ? result.nextSteps.join(\"\\n\") : result.nextSteps;\n return nextSteps ? `${base}\\n${nextSteps}` : base;\n}\n","import { CliError } from \"../api/errors.js\";\nimport { outputError, type OutputMode } from \"../output/formatter.js\";\nimport { printError } from \"../output/pretty.js\";\n\n/**\n * The shell every command shares: a CliError becomes this process's exit code,\n * printed as text in a terminal and as an error envelope when piped. Anything\n * else is a bug and keeps its stack.\n */\nexport async function withCommandErrors(mode: OutputMode, fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\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 fs from \"node:fs\";\nimport chalk from \"chalk\";\nimport { runTool } from \"../api/tool.js\";\nimport { validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `artifact-edit` MCP tool — change an artifact's files and\n * commit them without git. Every change in one call lands as ONE commit: either\n * all of them apply or none does.\n */\n\nexport type ArtifactChange = {\n op: \"str_replace\" | \"write\" | \"delete\" | \"move\";\n path?: string;\n oldText?: string;\n newText?: string;\n replaceAll?: boolean;\n content?: string;\n encoding?: \"utf8\" | \"base64\";\n assetUploadId?: string;\n fromPath?: string;\n toPath?: string;\n};\n\ntype EditResult = {\n success: boolean;\n revision?: string;\n previousRevision?: string;\n changedFiles?: Array<{ path: string; op: string; fromPath?: string; replacements?: number }>;\n};\n\nexport const editCommand = new Command(\"edit\")\n .summary(\"Change an artifact's files and commit them\")\n .description(\n \"Change an artifact's files and commit them, without git. All changes land as one commit.\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .requiredOption(\"-m, --message <message>\", \"Commit message\")\n .option(\n \"--base-revision <rev>\",\n \"The revision the edit applies to (from `anima explore`). Defaults to the artifact's current head\"\n )\n .option(\"--changes <json>\", \"The full change list as a JSON array — the general door\")\n .option(\"--changes-file <path>\", \"Read that JSON array from a file\")\n .option(\"--write <path>\", \"Shorthand: create or replace this file\")\n .option(\"--from-file <path>\", \"--write: take the content from this local file (default: stdin is not read)\")\n .option(\"--content <text>\", \"--write: the file's complete new content\")\n .option(\"--delete <path>\", \"Shorthand: delete this file\")\n .option(\"--move <path>\", \"Shorthand: rename this file (needs --to)\")\n .option(\"--to <path>\", \"--move: the new path\")\n .option(\"--replace <path>\", \"Shorthand: swap an exact snippet in this file (needs --old and --new)\")\n .option(\"--old <text>\", \"--replace: the exact text to replace\")\n .option(\"--new <text>\", \"--replace: the replacement text\")\n .option(\"--all\", \"--replace: replace every occurrence instead of requiring exactly one\")\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 (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const sessionId = parseArtifactUrl(artifactUrl);\n const changes = buildChanges(opts);\n\n // Without an explicit base the current head is the base, the way a commit\n // applies to the checkout you have. Reading it immediately before the\n // edit keeps the conflict window small, but it IS a window: pass\n // --base-revision from an earlier explore to be told about a concurrent\n // change instead of writing over it.\n const baseRevision = opts.baseRevision ?? (await currentRevision(sessionId, opts.apiUrl));\n\n const result = await runTool<EditResult>(\n \"artifact-edit\",\n { sessionId, baseRevision, commitMessage: opts.message, changes },\n { apiUrl: opts.apiUrl }\n );\n\n if (mode === \"pretty\") {\n console.log();\n printSuccess(\"Committed.\");\n for (const changed of result.changedFiles ?? []) {\n const detail =\n changed.op === \"move\"\n ? `${changed.fromPath} → ${changed.path}`\n : changed.replacements !== undefined\n ? `${changed.path} (${changed.replacements} replaced)`\n : changed.path;\n console.log(` ${chalk.gray(changed.op.padEnd(12))} ${detail}`);\n }\n console.log();\n printKeyValue(\"Revision\", result.revision ?? \"unknown\");\n console.log();\n console.log(\" The live artifact reflects this commit.\");\n console.log();\n } else {\n outputResult(mode, result);\n }\n });\n });\n\n/** The artifact's current head, for an edit that did not name a base. */\nasync function currentRevision(sessionId: string, apiUrl?: string): Promise<string> {\n const result = await runTool<{ success: boolean; revision?: string }>(\n \"artifact-explore\",\n { sessionId, action: \"tree\", limit: 1 },\n { apiUrl }\n );\n if (!result.revision) {\n throw validationError(\n \"Could not read the artifact's current revision. Pass --base-revision from `anima explore`.\"\n );\n }\n return result.revision;\n}\n\nexport function buildChanges(opts: Record<string, unknown>): ArtifactChange[] {\n const explicit = opts.changes ?? opts.changesFile;\n const shorthands = [opts.write, opts.delete, opts.move, opts.replace].filter(Boolean);\n\n if (explicit && shorthands.length) {\n throw validationError(\n \"--changes/--changes-file already carries the whole change list; drop the --write/--delete/--move/--replace shorthand.\"\n );\n }\n\n if (explicit) {\n const raw = opts.changesFile ? readFile(opts.changesFile as string) : (opts.changes as string);\n return parseChanges(raw);\n }\n\n if (shorthands.length !== 1) {\n throw validationError(\n \"Nothing to change. Pass --changes <json> (or --changes-file), or exactly one of \" +\n \"--write <path>, --delete <path>, --move <path> --to <path>, --replace <path> --old <text> --new <text>.\"\n );\n }\n\n if (opts.write) {\n if (opts.content === undefined && !opts.fromFile) {\n throw validationError(\"--write needs the file's content: pass --content <text> or --from-file <path>.\");\n }\n if (opts.content !== undefined && opts.fromFile) {\n throw validationError(\"Pass either --content or --from-file for --write, not both.\");\n }\n return [\n {\n op: \"write\",\n path: opts.write as string,\n content: opts.fromFile ? readFile(opts.fromFile as string) : (opts.content as string),\n },\n ];\n }\n\n if (opts.delete) {\n return [{ op: \"delete\", path: opts.delete as string }];\n }\n\n if (opts.move) {\n if (!opts.to) throw validationError(\"--move needs --to <path>, the new path.\");\n return [{ op: \"move\", fromPath: opts.move as string, toPath: opts.to as string }];\n }\n\n if (opts.old === undefined || opts.new === undefined) {\n throw validationError(\"--replace needs --old <text> and --new <text>. Pass --new \\\"\\\" to delete the snippet.\");\n }\n return [\n {\n op: \"str_replace\",\n path: opts.replace as string,\n oldText: opts.old as string,\n newText: opts.new as string,\n ...(opts.all ? { replaceAll: true } : {}),\n },\n ];\n}\n\nfunction parseChanges(raw: string): ArtifactChange[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw validationError(`--changes is not valid JSON: ${(err as Error).message}`);\n }\n if (!Array.isArray(parsed) || parsed.length === 0) {\n throw validationError(\"--changes must be a non-empty JSON array of change objects.\");\n }\n return parsed as ArtifactChange[];\n}\n\nfunction readFile(path: string): string {\n try {\n return fs.readFileSync(path, \"utf-8\");\n } catch (err) {\n throw validationError(`Could not read ${path}: ${(err as Error).message}`);\n }\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport { runTool } from \"../api/tool.js\";\nimport { apiError, validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { printSuccess, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `artifact-get_asset_upload_url` MCP tool, with the upload it\n * describes carried out: stage the file, POST it, and — when `--path` says\n * where it belongs — commit it with artifact-edit in the same run.\n *\n * Files up to 256 KB need no staging at all; `anima edit` takes them inline.\n */\n\ntype AssetUploadGrant = {\n success: boolean;\n assetUploadId?: string;\n uploadUrl?: string;\n uploadFields?: Record<string, string>;\n expiresAt?: string;\n maxBytes?: number;\n};\n\ntype EditResult = { success: boolean; revision?: string };\n\nexport const uploadAssetCommand = new Command(\"upload-asset\")\n .summary(\"Add an image, font or media file over 256 KB\")\n .description(\n \"Add a large image, font or media file (over 256 KB) to an artifact: stage it, upload it, and commit it at --path.\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .argument(\"<file>\", \"Local file to upload\")\n .option(\n \"--path <path>\",\n \"Where the asset lands in the artifact (e.g. public/hero.png). Omit to stage only and print the assetUploadId\"\n )\n .option(\"-m, --message <message>\", \"Commit message for the write\")\n .option(\"--base-revision <rev>\", \"The revision the commit applies to. Defaults to the current head\")\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, file: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n await withCommandErrors(mode, async () => {\n const sessionId = parseArtifactUrl(artifactUrl);\n const bytes = readAsset(file);\n\n progress.start(\"Staging the upload...\");\n const grant = await runTool<AssetUploadGrant>(\n \"artifact-get_asset_upload_url\",\n { sessionId, filename: path.basename(file) },\n { apiUrl: opts.apiUrl }\n );\n if (!grant.uploadUrl || !grant.uploadFields || !grant.assetUploadId) {\n throw apiError(\"The staging response carried no upload URL.\", grant);\n }\n if (grant.maxBytes !== undefined && bytes.byteLength > grant.maxBytes) {\n throw validationError(\n `${file} is ${bytes.byteLength} bytes; the limit is ${grant.maxBytes}. Push it with git instead: anima get-git-token ${sessionId}`\n );\n }\n\n progress.update(\"Uploading...\");\n await postAsset(grant.uploadUrl, grant.uploadFields, bytes, path.basename(file));\n logEvent(\"asset_uploaded\", { sessionId, assetUploadId: grant.assetUploadId });\n\n if (!opts.path) {\n progress.succeed(\"Uploaded — not committed yet.\");\n if (mode === \"pretty\") {\n console.log();\n printKeyValue(\"assetUploadId\", grant.assetUploadId);\n console.log();\n console.log(\" Commit it where it belongs with:\");\n console.log(\n ` ${chalk.cyan(\n `anima edit ${sessionId} -m \"Add asset\" --changes '[{\"op\":\"write\",\"path\":\"public/${path.basename(file)}\",\"assetUploadId\":\"${grant.assetUploadId}\"}]'`\n )}`\n );\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n assetUploadId: grant.assetUploadId,\n expiresAt: grant.expiresAt,\n nextSteps:\n \"Call `anima edit <artifact> --changes` with a write change carrying this assetUploadId and \" +\n \"the path the file should live at. The id is single-use and expires.\",\n });\n }\n return;\n }\n\n progress.update(\"Committing...\");\n const baseRevision = opts.baseRevision ?? (await currentRevision(sessionId, opts.apiUrl));\n const result = await runTool<EditResult>(\n \"artifact-edit\",\n {\n sessionId,\n baseRevision,\n commitMessage: opts.message ?? `Add ${opts.path}`,\n changes: [{ op: \"write\", path: opts.path, assetUploadId: grant.assetUploadId }],\n },\n { apiUrl: opts.apiUrl }\n );\n\n progress.succeed(\"Uploaded and committed!\");\n if (mode === \"pretty\") {\n console.log();\n printSuccess(`${file} → ${opts.path}`);\n printKeyValue(\"Revision\", result.revision ?? \"unknown\");\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n path: opts.path,\n assetUploadId: grant.assetUploadId,\n revision: result.revision,\n });\n }\n });\n });\n\n/**\n * S3 ignores every part sent after the file, so the signature fields go first\n * and `file` goes last. A successful upload answers 204 with an empty body.\n */\nasync function postAsset(\n uploadUrl: string,\n uploadFields: Record<string, string>,\n bytes: Buffer,\n filename: string\n): Promise<void> {\n const form = new FormData();\n for (const [key, value] of Object.entries(uploadFields)) {\n form.append(key, value);\n }\n form.append(\"file\", new Blob([new Uint8Array(bytes)]), filename);\n\n const response = await fetch(uploadUrl, { method: \"POST\", body: form });\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw apiError(`Asset upload failed: HTTP ${response.status}${detail ? ` — ${detail.slice(0, 300)}` : \"\"}`);\n }\n}\n\nasync function currentRevision(sessionId: string, apiUrl?: string): Promise<string> {\n const result = await runTool<{ success: boolean; revision?: string }>(\n \"artifact-explore\",\n { sessionId, action: \"tree\", limit: 1 },\n { apiUrl }\n );\n if (!result.revision) {\n throw validationError(\"Could not read the artifact's current revision. Pass --base-revision.\");\n }\n return result.revision;\n}\n\nfunction readAsset(file: string): Buffer {\n try {\n return fs.readFileSync(file);\n } catch (err) {\n throw validationError(`Could not read ${file}: ${(err as Error).message}`);\n }\n}\n","import { Command } from \"commander\";\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, printSuccess } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError, validationError } from \"../api/errors.js\";\n\ntype DeleteResult = {\n success: boolean;\n message?: string;\n code?: string;\n error?: string;\n reason?: string;\n};\n\n/** Mirror of `artifact-delete`: reversible soft deletion, never permanent deletion. */\nexport const deleteCommand = new Command(\"delete\")\n .summary(\"Delete an artifact (reversible: hidden, not erased)\")\n .description(\"Soft-delete an artifact only when explicitly requested (unpublish it first; content is retained)\")\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID to soft-delete\")\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 = parseArtifactUrl(artifactUrl);\n if (!sessionId) {\n throw validationError(\"An artifact URL or session ID is required\");\n }\n\n const auth = await resolveAuth(opts.apiUrl);\n progress.start(\"Deleting artifact...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<DeleteResult>(\"artifact-delete\", { sessionId })\n );\n\n if (!result.success) {\n throw apiError(result.message || result.reason || result.error || \"Artifact deletion failed\", result);\n }\n\n progress.succeed(\"Artifact deleted\");\n if (mode === \"pretty\") {\n printSuccess(result.message || `Artifact ${sessionId} is hidden and can be restored.`);\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 const detail = err.detail as { code?: unknown } | undefined;\n const code = typeof detail?.code === \"string\" ? detail.code : err.code;\n if (mode === \"pretty\") {\n printError(code === err.code ? err.message : `${code}: ${err.message}`);\n } else {\n outputError(mode, { 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 { runTool } from \"../api/tool.js\";\nimport { validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printInfo, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `review-*` MCP tools — the change requests humans address to\n * this credential's agent on their artifacts. Nothing pushes them, so `list` is\n * how the work arrives: run it when a human says they left comments, and at the\n * start of work on an artifact you have been reviewed on before.\n */\n\ntype Reply = { author: { kind: \"user\" | \"agent\"; name: string }; body: string; closing: boolean; createdAt: string };\n\ntype ReviewComment = {\n commentId: string;\n index: number;\n body: string;\n status: \"open\" | \"resolved\" | \"dismissed\";\n /** Addressed to nobody in particular, so every agent sees it. */\n unassigned?: boolean;\n anchor?: { kind: \"dom\" | \"markdownRange\" } & Record<string, unknown>;\n replies: Reply[];\n};\n\ntype Review = {\n reviewId: string;\n sessionId: string;\n artifactUrl: string;\n isLatest: boolean;\n author: { name: string; kind: \"user\" | \"agent\" };\n resolveTrailer: string;\n comments: ReviewComment[];\n createdAt: string;\n};\n\ntype ListResult = { success: boolean; reviews?: Review[]; message?: string };\ntype ResolveResult = { success: boolean; commentId?: string; resolved?: boolean; message?: string };\ntype ReplyResult = { success: boolean; commentId?: string; replied?: boolean; message?: string };\n\nconst listSubcommand = new Command(\"list\")\n .summary(\"Read the comments addressed to you\")\n .description(\"Read the review comments addressed to you, newest artifact activity first\")\n .argument(\"[artifactUrl]\", \"Limit to one artifact; omit for every review addressed to you\")\n .option(\"--limit <n>\", \"Maximum reviews to return (1-50, default 20)\")\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 (artifactUrl: string | undefined, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const args: Record<string, unknown> = {};\n if (artifactUrl) args.sessionId = parseArtifactUrl(artifactUrl);\n if (opts.limit !== undefined) args.limit = parseLimit(opts.limit);\n\n const result = await runTool<ListResult>(\"review-list\", args, { apiUrl: opts.apiUrl });\n\n if (mode === \"pretty\") {\n printReviews(result);\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nconst resolveSubcommand = new Command(\"resolve\")\n .summary(\"Close one comment without a commit\")\n .description(\"Close one comment without a commit — for a question answered, or a change you decided against\")\n .argument(\"<commentId>\", \"Comment to close, from `anima review list`\")\n .option(\"--note <text>\", \"What to tell the reviewer as the closing message\")\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 (commentId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const result = await runTool<ResolveResult>(\n \"review-resolve\",\n { commentId, ...(opts.note ? { note: opts.note } : {}) },\n { apiUrl: opts.apiUrl }\n );\n\n if (mode === \"pretty\") {\n console.log();\n // Already closed is not a failure — a commit trailer may have closed it.\n if (result.resolved) printSuccess(result.message ?? \"Comment resolved.\");\n else printInfo(result.message ?? \"Comment was already closed.\");\n console.log();\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nconst replySubcommand = new Command(\"reply\")\n .summary(\"Answer one comment, leaving it open\")\n .description(\"Say something back on one comment and LEAVE IT OPEN — to ask, report, or say you are blocked\")\n .argument(\"<commentId>\", \"Comment to reply to, from `anima review list`\")\n .requiredOption(\"-m, --message <message>\", \"What to say to the reviewer\")\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 (commentId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const result = await runTool<ReplyResult>(\n \"review-reply\",\n { commentId, message: opts.message },\n { apiUrl: opts.apiUrl }\n );\n\n if (mode === \"pretty\") {\n console.log();\n if (result.replied) printSuccess(result.message ?? \"Reply posted.\");\n else printInfo(result.message ?? \"The comment is closed, so nothing was posted.\");\n console.log();\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nexport const reviewCommand = new Command(\"review\")\n .summary(\"Read and answer the comments humans addressed to you\")\n .description(\"Read and answer the review comments humans addressed to you (list / resolve / reply)\")\n .addCommand(listSubcommand)\n .addCommand(resolveSubcommand)\n .addCommand(replySubcommand);\n\nfunction parseLimit(value: string): number {\n const limit = Number(value);\n if (!Number.isInteger(limit) || limit < 1 || limit > 50) {\n throw validationError(`--limit must be a whole number between 1 and 50 (got \"${value}\").`);\n }\n return limit;\n}\n\nfunction printReviews(result: ListResult): void {\n const reviews = result.reviews ?? [];\n console.log();\n\n if (reviews.length === 0) {\n console.log(` ${result.message ?? \"No open reviews are addressed to you.\"}`);\n console.log();\n return;\n }\n\n for (const review of reviews) {\n console.log(` ${chalk.bold(`Review ${review.reviewId}`)} ${chalk.gray(`by ${review.author.name}`)}`);\n console.log(` ${chalk.cyan.underline(review.artifactUrl)}`);\n if (!review.isLatest) {\n console.log(\n chalk.yellow(\" The artifact moved since this was written — check the comments still apply.\")\n );\n }\n console.log();\n\n for (const comment of review.comments) {\n const marks = [\n comment.status !== \"open\" ? chalk.gray(comment.status) : null,\n comment.unassigned ? chalk.yellow(\"unassigned\") : null,\n ]\n .filter(Boolean)\n .join(\" \");\n console.log(` ${chalk.bold(`#${comment.index}`)} ${comment.body}${marks ? ` ${marks}` : \"\"}`);\n console.log(chalk.gray(` ${comment.commentId}${describeAnchor(comment)}`));\n // Replies can add to or change the request, so they are shown, not counted.\n for (const reply of comment.replies ?? []) {\n console.log(chalk.gray(` ↳ ${reply.author.name}: ${reply.body}`));\n }\n console.log();\n }\n\n printKeyValue(\"To close these in a commit\", \"\");\n for (const line of review.resolveTrailer.split(\"\\n\")) {\n console.log(` ${chalk.gray(line)}`);\n }\n console.log();\n }\n}\n\nfunction describeAnchor(comment: ReviewComment): string {\n if (!comment.anchor) return \" — about the artifact as a whole\";\n const anchor = comment.anchor as Record<string, unknown>;\n const dom = anchor.dom as Record<string, unknown> | undefined;\n const markdown = anchor.markdown as Record<string, unknown> | undefined;\n\n if (dom?.sourceFile) {\n const instances = typeof dom.instanceCount === \"number\" && dom.instanceCount > 1 ? dom.instanceCount : 0;\n return ` — ${dom.sourceFile}${dom.sourceStart ? `:${dom.sourceStart}` : \"\"}${\n instances ? ` (shared markup: ${instances} instances)` : \"\"\n }`;\n }\n if (markdown?.quote) {\n return ` — on \"${String(markdown.quote).slice(0, 60)}\"`;\n }\n return \"\";\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport { apiError, validationError } from \"../api/errors.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { printSuccess } from \"../output/pretty.js\";\nimport { version } from \"../version.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Install the AgentGrid guide where this agent's runtime will find it.\n *\n * The prose is NOT kept here. It is fetched from the API's `/guide.md` — the\n * door-agnostic half of the same page `/connect` serves — so there is one copy\n * to maintain and it cannot go stale in a published tarball. What this command\n * adds is the part the server cannot know: the SKILL.md envelope,\n * a connect section written for someone who already has the CLI, and a command\n * reference generated from THIS binary's own command tree, so the syntax it\n * prints is the syntax this version actually accepts.\n */\n\n/** Where the guide lives on the API, alongside `/connect`. */\nconst GUIDE_PATH = \"/guide.md\";\n\nexport function createSkillCommand(): Command {\n return new Command(\"skill\")\n .summary(\"Install the AgentGrid guide as a skill your agent can read\")\n .description(\n \"Fetch the AgentGrid agent guide and write it as a SKILL.md your runtime can load, or print \" +\n \"it to stdout. The guide comes from the API, so it stays current; the command reference is \" +\n \"generated from this CLI's own commands.\"\n )\n .argument(\n \"[path]\",\n \"Where to write the SKILL.md (e.g. .claude/skills/agentgrid/SKILL.md). Omit to print to stdout\"\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 (target: string | undefined, opts, command: Command) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const apiUrl = resolveApiUrl(opts.apiUrl);\n const guide = await fetchGuide(apiUrl);\n\n // The program owns every command; reach it through this one's parent so\n // the reference lists whatever is registered, with no second list to keep.\n const program = command.parent ?? command;\n // Reference before narrative: the summaries are a map, not a tutorial, and\n // an agent that already knows AgentGrid is here for the exact syntax.\n const body = [connectSection(), commandReference(program), guide.trim(), provenance(apiUrl)].join(\n \"\\n\\n\"\n );\n const document = `${frontmatter()}\\n${body}\\n`;\n\n if (!target) {\n process.stdout.write(document.endsWith(\"\\n\") ? document : `${document}\\n`);\n return;\n }\n\n writeDocument(target, document);\n logEvent(\"skill_installed\", { path: target, bytes: document.length });\n\n if (mode === \"pretty\") {\n console.log();\n printSuccess(`Skill written to ${chalk.cyan(target)}`);\n console.log(` ${chalk.gray(`${document.length} bytes, from ${apiUrl}${GUIDE_PATH}`)}`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n path: path.resolve(target),\n bytes: document.length,\n source: `${apiUrl}${GUIDE_PATH}`,\n });\n }\n });\n });\n}\n\nexport const skillCommand = createSkillCommand();\n\nasync function fetchGuide(apiUrl: string): Promise<string> {\n const url = `${apiUrl.replace(/\\/$/, \"\")}${GUIDE_PATH}`;\n logEvent(\"skill_fetch\", { url });\n\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw apiError(`Could not reach ${url}: ${(err as Error).message}`);\n }\n if (response.status === 404) {\n throw apiError(\n `${url} returned 404. This API does not serve the agent guide yet — point --api-url at one that does.`\n );\n }\n if (!response.ok) {\n throw apiError(`Could not fetch the guide: HTTP ${response.status} from ${url}`);\n }\n const body = await response.text();\n if (!body.trim()) {\n throw apiError(`${url} returned an empty guide.`);\n }\n return body;\n}\n\n/**\n * Frontmatter is what makes a skill discoverable: the description decides\n * whether a runtime loads it for the task at hand, so it names the triggers\n * rather than describing the file.\n */\nfunction frontmatter(): string {\n return [\n \"---\",\n \"name: agentgrid\",\n \"description: >-\",\n \" Host, change, publish and share artifacts on AgentGrid from the command line.\",\n \" Use when asked to share an app or a document with a human, put work somewhere\",\n \" they can see it, create or edit an AgentGrid artifact, publish one to a live\",\n \" URL, or answer review comments left on one.\",\n \"---\",\n ].join(\"\\n\");\n}\n\n/**\n * The server's guide assumes a token. This is the part it cannot write: getting\n * one, for a reader who already has the CLI — so no raw-HTTP fallback, which is\n * half of what /connect spends its doors on.\n */\nfunction connectSection(): string {\n return `# AgentGrid\n\nAn **artifact** is a hosted app or document that is also a real git repository.\nEvery command below runs one AgentGrid tool for you.\n\n## Connect first\n\nYou act as a scoped agent identity a human approved and can revoke. Three doors —\nthe first is the usual one, because you arrive with something to show and they\nneed no account until they claim it:\n\n\\`\\`\\`bash\n# 1. You lead: create with no credential at all, then wait for the claim\nnpx @animaapp/cli@latest create --anonymous -t import --from ./my-project \\\\\n --client-name \"<your product name>\" --json # returns artifactUrl — send it to your human\nnpx @animaapp/cli@latest login --handoff --json # blocks until they claim; stores your credentials\n\n# 2. A human is reachable and can approve a short code\nnpx @animaapp/cli@latest login\n\n# 3. A human already sent you an invite link\nnpx @animaapp/cli@latest login --invite <url-or-code>\n\\`\\`\\`\n\nCredentials live in \\`~/.config/anima/\\` and the CLI renews them for you. Check\nwith \\`anima auth --status\\`. Every command takes \\`--json\\` for machine-readable\noutput on stdout, with progress on stderr.`;\n}\n\n/** Every registered command, straight from the program — so it cannot drift. */\nexport function commandReference(program: Command): string {\n const rows: string[] = [];\n\n for (const command of program.commands) {\n if (command.name() === \"help\") continue;\n const subcommands = command.commands.filter((sub) => sub.name() !== \"help\");\n if (subcommands.length > 0) {\n for (const sub of subcommands) {\n rows.push(row(`${command.name()} ${sub.name()}`, sub));\n }\n continue;\n }\n rows.push(row(command.name(), command));\n }\n\n return [\n \"## Command reference\",\n \"\",\n `Generated from \\`@animaapp/cli\\` ${version}, so this is what your copy accepts.`,\n \"Run `anima <command> --help` for a command's full options.\",\n \"\",\n \"| Command | What it does |\",\n \"| ------- | ------------ |\",\n ...rows,\n ].join(\"\\n\");\n}\n\nfunction row(name: string, command: Command): string {\n const usage = command.usage().replace(/\\[options\\]\\s*/, \"\").trim();\n const invocation = `anima ${name}${usage ? ` ${usage}` : \"\"}`;\n const summary = (command.summary() || command.description() || \"\").split(\"\\n\")[0];\n return `| \\`${invocation}\\` | ${escapePipes(summary)} |`;\n}\n\nconst escapePipes = (text: string): string => text.replace(/\\|/g, \"\\\\|\");\n\nfunction provenance(apiUrl: string): string {\n return `---\\n\\n_Guide fetched from ${apiUrl}${GUIDE_PATH}; command reference generated by @animaapp/cli ${version}._`;\n}\n\n/** The skill file is ours outright, so writing it is a plain overwrite. */\nfunction writeDocument(target: string, document: string): void {\n const directory = path.dirname(path.resolve(target));\n try {\n fs.mkdirSync(directory, { recursive: true });\n } catch (err) {\n throw validationError(`Could not create ${directory}: ${(err as Error).message}`);\n }\n try {\n fs.writeFileSync(target, document, \"utf-8\");\n } catch (err) {\n throw validationError(`Could not write ${target}: ${(err as Error).message}`);\n }\n}\n"],"mappings":"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","names":["Command","chalk","required","fs","path","fs","path","os","CONFIG_DIR","path","status","chalk","Command","chalk","Command","chalk","relative","Command","chalk","Command","chalk","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","chalk","Command","chalk","Command","fs","chalk","Command","chalk","path","fs","Command","fs","path","chalk","Command","path","chalk","currentRevision","fs","Command","Command","Command","chalk","Command","parseLimit","chalk","Command","fs","path","chalk","Command","program","chalk","path","fs","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/clientIdentity.ts","../src/output/formatter.ts","../src/output/progress.ts","../src/output/pretty.ts","../src/utils/figma.ts","../src/utils/projectSource.ts","../src/utils/artifactUrl.ts","../src/utils/waitForArtifact.ts","../src/api/anonymousCreate.ts","../src/utils/workspaceFlag.ts","../src/commands/createKnowledge.ts","../src/commands/runner.ts","../src/commands/list.ts","../src/commands/workspaces.ts","../src/commands/status.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","../src/commands/explore.ts","../src/api/tool.ts","../src/commands/edit.ts","../src/commands/uploadAsset.ts","../src/commands/delete.ts","../src/commands/review.ts","../src/commands/skill.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createCommand } from \"./commands/create.js\";\nimport { createKnowledgeCommand } from \"./commands/createKnowledge.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { workspacesCommand } from \"./commands/workspaces.js\";\nimport { statusCommand } from \"./commands/status.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 { exploreCommand } from \"./commands/explore.js\";\nimport { editCommand } from \"./commands/edit.js\";\nimport { uploadAssetCommand } from \"./commands/uploadAsset.js\";\nimport { deleteCommand } from \"./commands/delete.js\";\nimport { reviewCommand } from \"./commands/review.js\";\nimport { skillCommand } from \"./commands/skill.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 — create, change, publish and share artifacts on AgentGrid.\nAn artifact is a real git repository, and every command below runs one\nAgentGrid MCP tool for you. The command list is at the bottom; run\n\"anima <command> --help\" for a command's own options.\n\nTHE MAIN FLOW (build something and put it on AgentGrid):\n 1. anima login # once; a human approves\n 2. anima 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 (can create in several workspaces? add --workspace <id>; see \"workspaces\")\n 3. Change it. Two doors, same git repository:\n - no clone: \"explore\" to read the files, \"edit\" to commit them. Needs no\n shell, no git binary and no network of its own — prefer it.\n - a real checkout: \"get-git-token\" (create already returns one), then\n git clone / commit / push. Worth it for a large refactor, running the\n project, branches or rewriting history.\n 4. Share the artifactUrl — app.agentgrid.io/artifacts/<sessionId>. That IS\n sharing: the artifact is already visible there. Do NOT run \"publish\"\n unless a human explicitly asked for a public site; offer it as a\n follow-up question instead.\n\nTIMING — how long the COMMAND blocks, not how long the server takes:\n create -t p2c|l2c|f2c BLOCKS 3-7 min. The generation itself is\n asynchronous, but create waits it out for you, so\n what it prints is a finished app and a failed\n generation exits non-zero. Keep the default\n 600000ms --timeout. Pass --no-wait to get the\n sessionId back in seconds and do the waiting\n yourself with \"anima status <sessionId> --wait\".\n publish / unpublish BLOCKS 1-3 min\n everything else seconds, create -t empty|import included\n\nAUTHENTICATION:\n anima skill <path> # install this guide where your runtime reads skills\n anima login # device flow — a human approves on any device\n anima login --invite <url> # redeem a pre-approved invite (no approval step)\n anima create --anonymous … # no account at all; hand off to a human later\n Credentials live in ~/.config/anima/; \"logout\" removes everything.\n\nEXAMPLES:\n anima create -t import --from ./my-project\n anima status <sessionId> --wait\n anima explore <sessionId> --search \"buttonColor\"\n anima edit <sessionId> -m \"Blue pill\" --replace src/App.tsx --old red --new blue\n anima review list # what humans asked you to change\n anima publish <sessionId> # only on explicit request\n\nOUTPUT: pretty text in a terminal; a single JSON object on stdout when piped\n or given --json. Progress and prompts go to stderr, so stdout stays clean.\n Add --verbose to stream progress in JSON mode.`\n )\n .version(version, \"-v, --version\");\n\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\nprogram.addCommand(workspacesCommand);\nprogram.addCommand(listCommand);\nprogram.addCommand(createCommand);\nprogram.addCommand(createKnowledgeCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(exploreCommand);\nprogram.addCommand(editCommand);\nprogram.addCommand(uploadAssetCommand);\nprogram.addCommand(getGitTokenCommand);\nprogram.addCommand(reviewCommand);\nprogram.addCommand(duplicateCommand);\nprogram.addCommand(publishCommand);\nprogram.addCommand(unpublishCommand);\nprogram.addCommand(updateCommand);\nprogram.addCommand(deleteCommand);\nprogram.addCommand(codegenCommand);\nprogram.addCommand(skillCommand);\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 { artifactUrlFor } from \"../utils/artifactUrl.js\";\nimport { waitForArtifact } from \"../utils/waitForArtifact.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 { workspaceFlag } from \"../utils/workspaceFlag.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 /** 'generating' for p2c/l2c/f2c: the job runs in the background. */\n status?: \"generating\";\n /** The artifact's page in Agent Grid — the link to share. */\n artifactUrl?: string;\n /** App artifacts only: the Playground editor and the rendered preview. */\n playgroundUrl?: string;\n previewUrl?: 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 message?: 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 .summary(\"Create an artifact: your code, an empty repo, or AI generation\")\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(\n \"-w, --workspace <id>\",\n \"The workspace to create it in (id from `anima workspaces`). Optional when you can create in \" +\n \"only one workspace; otherwise required, since there is no default\"\n )\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(\n \"--no-wait\",\n \"Return as soon as generation starts (p2c/l2c/f2c), instead of waiting for the finished app. Poll with `anima status <sessionId> --wait`\"\n )\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 timeoutMs = parseInt(opts.timeout, 10);\n const deadline = Date.now() + timeoutMs;\n\n const { result, settled } = await withMcp(mcpConfig, async (client) => {\n const created = await client.callTool<CreateResult>(\"artifact-create\", args, { timeoutMs });\n if (!created.success || !created.sessionId) return { created };\n\n // p2c/l2c/f2c are asynchronous: artifact-create returns the moment the\n // job is enqueued. Without this wait the command would report success\n // and hand over a link for an app that is still being built.\n if (created.status !== \"generating\" || !opts.wait) return { created };\n\n progress.update(\"Generating your app...\");\n const status = await waitForArtifact(client, created.sessionId, {\n deadline,\n onProgress: (message) => progress.update(message),\n });\n return { created, status };\n }).then(({ created, status }) => ({ result: created, settled: status }));\n\n if (!result.success || !result.sessionId) {\n const message = result.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 if (settled?.status === \"failed\") {\n throw apiError(settled.error || \"Generation failed\", settled);\n }\n\n // The settled status carries the final URLs. While a job is in flight\n // `playgroundUrl` is the /loading page, not the editor, so prefer what\n // the finished status returned whenever there is one.\n const artifactUrl = settled?.artifactUrl || result.artifactUrl || artifactUrlFor(result.sessionId);\n const playgroundUrl = settled?.playgroundUrl ?? result.playgroundUrl;\n const previewUrl = settled?.previewUrl ?? result.previewUrl;\n const status = settled?.status ?? result.status ?? \"ready\";\n\n progress.succeed(settled ? \"Your app is ready!\" : \"Artifact created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({\n sessionId: result.sessionId,\n artifactUrl,\n playgroundUrl,\n });\n if (status === \"generating\") {\n console.log(\n ` Still generating. Wait for it with ${chalk.cyan(`anima status ${result.sessionId} --wait`)}.`\n );\n console.log();\n }\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 status,\n artifactUrl,\n ...(playgroundUrl ? { playgroundUrl } : {}),\n ...(previewUrl ? { previewUrl } : {}),\n ...(settled?.name ? { name: settled.name } : {}),\n ...(status === \"generating\"\n ? {\n nextSteps: `Generation is still running. Wait for it with: anima status ${result.sessionId} --wait`,\n }\n : {}),\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\nexport function 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 workspaceFlag(opts.workspace);\n if (opts.workspace !== undefined && opts.anonymous) {\n throw validationError(\n \"--workspace does not apply to --anonymous creates — they belong to no team until a human claims them\"\n );\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\nexport function 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 ...(opts.workspace !== undefined ? { workspaceId: opts.workspace } : {}),\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 if (opts.workspace !== undefined) args.workspaceId = opts.workspace;\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 // A refused tool call arrives as MCP error text, prefixed for the agent that would read it raw.\n const text = message.replace(/^Error: /, \"\");\n return new CliError(\"API_ERROR\", withWorkspaceHint(text), EXIT_CODES.API_ERROR, detail);\n}\n\n/** The server names its MCP parameter; on the command line it is the --workspace flag. */\nfunction withWorkspaceHint(message: string): string {\n if (/\\bworkspaceId\\b/.test(message)) {\n return `${message}\\nPass it with --workspace <id>; \\`anima workspaces\\` lists the ids.`;\n }\n if (message === \"Workspace not found\") {\n return `${message}\\n\\`anima workspaces\\` lists the workspaces you can reach, with their ids.`;\n }\n return message;\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 { ANIMA_CLIENT_IDENTITY } from \"../clientIdentity.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_CLIENT_IDENTITY.name, version: ANIMA_CLIENT_IDENTITY.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 \"X-Anima-Client-Type\": ANIMA_CLIENT_IDENTITY.type,\n \"X-Anima-Client-Name\": ANIMA_CLIENT_IDENTITY.name,\n \"X-Anima-Client-Version\": ANIMA_CLIENT_IDENTITY.version,\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 // The server lists a tool only to a caller that may use it: an agent needs read to list and\n // write to create, in some workspace of the team.\n if ((err as { code?: number })?.code === ErrorCode.InvalidParams && /\\bnot found\\b/.test((err as Error).message)) {\n throw apiError(\n `${name} is not available to this credential. An agent is offered it only once a human has ` +\n \"granted it the access it needs in a workspace of this team (read to list, write to create).\"\n );\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","import { version } from \"./version.js\";\n\n/** Non-secret product identity sent with MCP requests and anonymous artifact creates. */\nexport const ANIMA_CLIENT_IDENTITY = {\n type: \"cli\",\n name: \"anima-cli\",\n version,\n} as const;","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\n/**\n * `artifactUrl` is the artifact's page in Agent Grid and the link to share.\n * `playgroundUrl` is the editor and exists only for `app` artifacts, so it is\n * shown beside that link rather than in place of it.\n */\nexport function printSessionResult(result: {\n sessionId: string;\n artifactUrl?: 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.artifactUrl) {\n printKeyValue(\"Your artifact\", chalk.cyan.underline(result.artifactUrl));\n }\n if (result.playgroundUrl) {\n printKeyValue(\"Edit in Playground\", 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","/**\n * An artifact's page in Agent Grid — `artifactUrl` in every MCP tool result,\n * and the link to hand a human. The Playground host (`playgroundUrl` to edit,\n * `previewUrl` to render) answers only for `app` artifacts, so it is never the\n * link to fall back on.\n */\nexport const ARTIFACT_BASE = \"https://app.agentgrid.io/artifacts\";\n\n/** The artifact page for a session, for results that predate `artifactUrl`. */\nexport function artifactUrlFor(sessionId: string): string {\n return `${ARTIFACT_BASE}/${sessionId}`;\n}\n\n/**\n * Parse an artifact reference to its session ID.\n * Supported formats:\n * - https://app.agentgrid.io/artifacts/SESSION_ID\n * - https://dev.animaapp.com/chat/SESSION_ID (the Playground host)\n * - Just a session ID string\n */\nexport function parseArtifactUrl(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: /artifacts/SESSION_ID or /chat/SESSION_ID — the session id is\n // the segment after either marker.\n const markerIndex = parts.findIndex((p) => p === \"artifacts\" || p === \"chat\");\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 type { AnimaMcpClient } from \"../api/mcp.js\";\nimport { CliError, EXIT_CODES } from \"../api/errors.js\";\nimport { logEvent } from \"../output/log.js\";\n\n/**\n * `artifact-status` — the only way to learn that a generation finished.\n *\n * `artifact-create` no longer blocks: p2c/l2c/f2c return immediately with\n * `status: 'generating'` while the job runs in the background. A `wait: true`\n * status call blocks server-side for about 45 seconds and comes back still\n * generating if the job outlives that, so the waiting is a loop of those calls.\n */\n\nexport type ArtifactStatusResult = {\n success: boolean;\n sessionId?: string;\n status?: \"generating\" | \"ready\" | \"failed\";\n /** 0–100, while generating. */\n progress?: number;\n name?: string;\n thumbnailUrl?: string;\n artifactType?: \"app\" | \"markdown\" | \"asset\";\n /** Absent while failed — a failed job has no page to open. */\n artifactUrl?: string;\n playgroundUrl?: string;\n previewUrl?: string;\n /** Failure reason, when status is 'failed'. */\n error?: string;\n reason?: string;\n nextStep?: string;\n};\n\n/** Room for the server's ~45s wait plus the round trip. Progress resets it. */\nconst STATUS_CALL_TIMEOUT_MS = 120_000;\n\nexport async function fetchArtifactStatus(\n client: AnimaMcpClient,\n sessionId: string,\n options: { wait?: boolean; onProgress?: (message: string) => void } = {}\n): Promise<ArtifactStatusResult> {\n return client.callTool<ArtifactStatusResult>(\n \"artifact-status\",\n { sessionId, wait: options.wait ?? false },\n {\n timeoutMs: STATUS_CALL_TIMEOUT_MS,\n onProgress: options.onProgress\n ? (p) => options.onProgress!(p.message ?? `Generating (${Math.round(p.progress * 100)}%)...`)\n : undefined,\n }\n );\n}\n\n/**\n * Poll until the artifact is ready or failed. Returns the terminal status;\n * throws TIMEOUT if `deadline` passes while it is still generating — the job\n * itself keeps running, so the message says how to pick the wait back up.\n */\nexport async function waitForArtifact(\n client: AnimaMcpClient,\n sessionId: string,\n options: { deadline: number; onProgress?: (message: string) => void } = { deadline: Date.now() }\n): Promise<ArtifactStatusResult> {\n for (;;) {\n const result = await fetchArtifactStatus(client, sessionId, {\n wait: true,\n onProgress: options.onProgress,\n });\n\n if (!result.success) {\n throw new CliError(\n \"API_ERROR\",\n result.reason || result.error || \"Could not read the artifact's status\",\n EXIT_CODES.API_ERROR,\n result\n );\n }\n if (result.status !== \"generating\") {\n logEvent(\"generation_settled\", { sessionId, status: result.status });\n return result;\n }\n\n // Still generating. The next call blocks server-side for another ~45s, so\n // starting one past the deadline would overshoot it by that much.\n if (Date.now() >= options.deadline) {\n logEvent(\"generation_wait_timeout\", { sessionId, progress: result.progress });\n throw generationTimeoutError(sessionId, result.progress);\n }\n options.onProgress?.(\n result.progress !== undefined ? `Generating (${result.progress}%)...` : \"Generating...\"\n );\n }\n}\n\nfunction generationTimeoutError(sessionId: string, progress?: number): CliError {\n const reached = progress !== undefined ? ` (reached ${progress}%)` : \"\";\n return new CliError(\n \"TIMEOUT\",\n `Still generating${reached} when the wait budget ran out. Generation is NOT cancelled — it ` +\n `keeps running in the background.\\n` +\n `Pick the wait back up with: anima status ${sessionId} --wait\\n` +\n `Or allow longer next time with --timeout <ms>.`,\n EXIT_CODES.TIMEOUT,\n { sessionId, progress }\n );\n}\n","import { apiError } from \"./errors.js\";\nimport { logEvent } from \"../output/log.js\";\nimport { ANIMA_CLIENT_IDENTITY } from \"../clientIdentity.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 clientType: ANIMA_CLIENT_IDENTITY.type,\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 { validationError } from \"../api/errors.js\";\n\n/**\n * The `--workspace` value, or undefined when the flag was not passed. An empty value (an unset\n * `$WS` in a script) is refused: dropping it would list or create across every workspace instead.\n */\nexport function workspaceFlag(value: string | undefined): string | undefined {\n if (value !== undefined && value.trim() === \"\") {\n throw validationError(\"--workspace needs a workspace id; `anima workspaces` lists them\");\n }\n return value;\n}\n","import { Command } from \"commander\";\nimport { workspaceFlag } from \"../utils/workspaceFlag.js\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printKeyValue, printSessionResult } from \"../output/pretty.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, validationError } from \"../api/errors.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\ntype CreateKnowledgeResult = {\n success: boolean;\n sessionId?: string;\n revision?: string;\n artifactUrl?: string;\n playgroundUrl?: string;\n previewUrl?: string;\n name?: string;\n framework?: \"html\" | \"react\";\n artifactType?: \"knowledge\";\n fileCount?: number;\n skippedFiles?: string[];\n gitRemoteUrl?: string;\n access?: \"ro\" | \"rw\";\n expiresAt?: string;\n nextSteps?: string;\n error?: string;\n reason?: string;\n message?: string;\n};\n\nexport function buildCreateKnowledgeArgs(\n name?: string,\n workspaceId?: string\n): { name?: string; workspaceId?: string } {\n if (name !== undefined && name.length > 120) {\n throw validationError(\"--name must be at most 120 characters\");\n }\n return {\n ...(name === undefined ? {} : { name }),\n ...(workspaceFlag(workspaceId) === undefined ? {} : { workspaceId }),\n };\n}\n\nexport function makeCreateKnowledgeCommand(): Command {\n return new Command(\"create-knowledge\")\n .summary(\"Create a knowledge artifact from Anima's template\")\n .description(\n \"Create a ready knowledge artifact from Anima's server-provided template. The template supplies the files and framework; only an optional display name is accepted.\"\n )\n .option(\"--name <name>\", 'Display name (defaults to \"Untitled project\"; max 120 characters)')\n .option(\n \"-w, --workspace <id>\",\n \"The workspace to create it in (id from `anima workspaces`). Optional when you can create in \" +\n \"only one workspace; otherwise required, since there is no default\"\n )\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 (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n await withCommandErrors(mode, async () => {\n try {\n await run();\n } catch (err) {\n progress.fail(\"Failed\");\n throw err;\n }\n });\n\n async function run(): Promise<void> {\n const args = buildCreateKnowledgeArgs(opts.name, opts.workspace);\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(\"Creating knowledge artifact from template...\");\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<CreateKnowledgeResult>(\"artifact-create_knowledge\", args)\n );\n\n if (!result.success || !result.sessionId) {\n throw apiError(result.message || result.reason || result.error || \"Knowledge artifact creation failed\", result);\n }\n\n progress.succeed(\"Knowledge artifact created\");\n if (mode === \"pretty\") {\n printSessionResult({\n sessionId: result.sessionId,\n artifactUrl: result.artifactUrl,\n playgroundUrl: result.playgroundUrl,\n });\n if (result.fileCount !== undefined) {\n printKeyValue(\"Template files\", String(result.fileCount));\n }\n console.log();\n } else {\n outputResult(mode, result);\n }\n }\n });\n}\n\nexport const createKnowledgeCommand = makeCreateKnowledgeCommand();\n","import { CliError } from \"../api/errors.js\";\nimport { outputError, type OutputMode } from \"../output/formatter.js\";\nimport { printError } from \"../output/pretty.js\";\n\n/**\n * The shell every command shares: a CliError becomes this process's exit code,\n * printed as text in a terminal and as an error envelope when piped. Anything\n * else is a bug and keeps its stack.\n */\nexport async function withCommandErrors(mode: OutputMode, fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\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 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 { artifactUrlFor } from \"../utils/artifactUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError } from \"../api/errors.js\";\nimport { workspaceFlag } from \"../utils/workspaceFlag.js\";\n\n/**\n * Mirror of the `workspace-list_artifacts` MCP tool. Lists the artifacts you can\n * read, most-recently-updated first, so an agent can resume existing work\n * instead of creating duplicates. Spans every workspace you can read unless\n * `--workspace` names one.\n */\n\ntype Artifact = {\n name: string;\n type: \"app\" | \"markdown\" | \"asset\" | \"knowledge\";\n sessionId: string;\n workspaceId?: string;\n workspaceName?: string;\n updatedAt: string;\n};\n\ntype ListArtifactsResult = {\n success: boolean;\n artifacts?: Artifact[];\n truncated?: boolean;\n error?: string;\n reason?: string;\n message?: string;\n};\n\nexport const listCommand = new Command(\"list\")\n .summary(\"List the artifacts you can read, most-recently-updated first\")\n .aliases([\"ls\", \"artifacts\"])\n .description(\n \"List the artifacts you can read, across every workspace you can reach or in one (most-recently-updated \" +\n \"first), so you can resume existing work.\"\n )\n .option(\n \"-w, --workspace <id>\",\n \"Only this workspace (id from `anima workspaces`); omit to span every workspace you can read\"\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 workspaceId = workspaceFlag(opts.workspace);\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n client.callTool<ListArtifactsResult>(\n \"workspace-list_artifacts\",\n workspaceId !== undefined ? { workspaceId } : {}\n )\n );\n\n if (!result.success) {\n const message =\n result.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 workspaceId !== undefined\n ? \" Nothing you can read in that workspace.\"\n : \" No artifacts you can read — 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 console.log(` ${chalk.gray(\"session:\")} ${a.sessionId}`);\n if (a.workspaceName) {\n console.log(` ${chalk.gray(\"workspace:\")} ${a.workspaceName}`);\n }\n console.log(` ${chalk.gray(\"updated:\")} ${formatUpdatedAt(a.updatedAt)}`);\n console.log(` ${chalk.cyan.underline(artifactUrlFor(a.sessionId))}`);\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 // The listing tool returns no URL; deriving it here saves every caller\n // the same string concatenation, and keeps one definition of the link.\n artifacts: artifacts.map((a) => ({ ...a, artifactUrl: artifactUrlFor(a.sessionId) })),\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 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 { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `workspace-list_workspaces` MCP tool. Workspace ids are opaque,\n * so this is the only way to obtain one for `list --workspace` or\n * `create --workspace`.\n */\n\ntype Workspace = {\n workspaceId: string;\n name: string;\n isGeneral: boolean;\n capabilities: string[];\n};\n\ntype ListWorkspacesResult = {\n success: boolean;\n workspaces?: Workspace[];\n nextSteps?: string;\n error?: string;\n reason?: string;\n message?: string;\n};\n\nexport const workspacesCommand = new Command(\"workspaces\")\n .summary(\"List the workspaces you can reach, and what you may do in each\")\n .aliases([\"ws\"])\n .description(\n \"List the workspaces you can read in your team, with the capabilities you hold in each. \" +\n \"Use a workspace id with `list --workspace` or `create --workspace`.\"\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<ListWorkspacesResult>(\"workspace-list_workspaces\", {})\n );\n\n if (!result.success) {\n const message =\n result.message || result.reason || result.error || \"Could not list workspaces\";\n throw apiError(message, result);\n }\n\n const workspaces = result.workspaces ?? [];\n logEvent(\"workspaces_listed\", { count: workspaces.length });\n\n if (mode === \"pretty\") {\n console.log();\n if (workspaces.length === 0) {\n // Never \"this team has no workspaces\": an empty list is a narrow grant.\n console.log(\" You cannot reach any workspace in this team.\");\n console.log(\n chalk.gray(\" Someone who manages the team can grant you access to one.\")\n );\n console.log();\n } else {\n for (const workspace of workspaces) {\n const label = workspace.isGeneral && workspace.name !== \"General\" ? chalk.gray(\" (General)\") : \"\";\n console.log(` ${chalk.bold(workspace.name)}${label}`);\n console.log(` ${chalk.gray(\"id:\")} ${workspace.workspaceId}`);\n console.log(\n ` ${chalk.gray(\"you can:\")} ${workspace.capabilities.join(\", \") || chalk.gray(\"nothing\")}`\n );\n console.log();\n }\n }\n } else {\n outputResult(mode, { success: true, workspaces });\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 { 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, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { fetchArtifactStatus, waitForArtifact } from \"../utils/waitForArtifact.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `artifact-status` MCP tool. Generation (p2c/l2c/f2c) is\n * asynchronous, so this is how a caller learns it finished — `create` waits by\n * default, and this command picks that wait back up or takes a snapshot.\n */\nexport const statusCommand = new Command(\"status\")\n .summary(\"Check whether an artifact finished generating\")\n .description(\n \"Check whether an artifact finished generating. --wait blocks until it is ready or failed.\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .option(\"--wait\", \"Block until generation finishes instead of returning a snapshot\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"How long --wait may block\", \"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 (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 = parseArtifactUrl(artifactUrl);\n const auth = await resolveAuth(opts.apiUrl);\n\n progress.start(opts.wait ? \"Waiting for generation...\" : \"Checking status...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) =>\n opts.wait\n ? waitForArtifact(client, sessionId, {\n deadline: Date.now() + parseInt(opts.timeout, 10),\n onProgress: (message) => progress.update(message),\n })\n : fetchArtifactStatus(client, sessionId)\n );\n\n if (!result.success) {\n throw apiError(result.reason || result.error || \"Could not read the artifact's status\", result);\n }\n\n progress.succeed(`Status: ${result.status}`);\n\n if (mode === \"pretty\") {\n printArtifactStatus(sessionId, result);\n } else {\n outputResult(mode, { ...result, sessionId: result.sessionId ?? sessionId });\n }\n\n // A failed generation is a failed command: an agent that only checks the\n // exit code must not read \"failed\" as \"done\".\n if (result.status === \"failed\") {\n process.exit(1);\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\nfunction printArtifactStatus(\n sessionId: string,\n result: Awaited<ReturnType<typeof fetchArtifactStatus>>\n): void {\n console.log();\n if (result.status === \"ready\") {\n printSuccess(\"Ready!\");\n } else if (result.status === \"failed\") {\n printError(`Generation failed: ${result.error ?? \"no reason given\"}`);\n }\n printKeyValue(\"Session ID\", result.sessionId ?? sessionId);\n printKeyValue(\"Status\", result.status ?? \"unknown\");\n if (result.name) printKeyValue(\"Name\", result.name);\n if (result.status === \"generating\" && result.progress !== undefined) {\n printKeyValue(\"Progress\", `${result.progress}%`);\n }\n if (result.artifactUrl) {\n printKeyValue(\"Your artifact\", chalk.cyan.underline(result.artifactUrl));\n }\n if (result.playgroundUrl) {\n printKeyValue(\"Edit in Playground\", chalk.cyan.underline(result.playgroundUrl));\n }\n if (result.nextStep) {\n console.log();\n console.log(` Still generating — run this again with --wait to keep waiting.`);\n }\n console.log();\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 .summary(\"Deploy to a public live URL (only when asked)\")\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 .summary(\"Convert a Figma design to local code files\")\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 { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { gitConfigCommands, 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 .summary(\"Mint git access to an artifact's repository\")\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 = parseArtifactUrl(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 // A clone has no identity of its own: without this the push is\n // attributed to whatever git identity this machine happens to carry.\n if (grant.commitAuthor) {\n console.log(\" In the clone, set who your commits are from:\");\n console.log(` ${chalk.cyan(gitConfigCommands(grant.commitAuthor))}`);\n console.log();\n }\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 ...(grant.commitAuthor\n ? {\n commitAuthor: grant.commitAuthor,\n gitConfigCommand: gitConfigCommands(grant.commitAuthor),\n }\n : {}),\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,\n * commitAuthor }` on a grant, or `{ success: false, error, reason }` on a\n * denial. The MCP client (api/mcp.ts) already JSON-parses tool text, so this\n * receives the parsed object — a string only arrives if that parse failed. The\n * clone URL embeds a 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 * Who the server attributes commits from this clone to — the authenticated\n * agent, or the human behind the credential. A clone carries no identity of\n * its own, so without applying this a push is attributed to whatever local\n * git identity the machine happens to have.\n */\n commitAuthor?: { name: string; email: 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 commitAuthor?: { name?: unknown; email?: unknown };\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 ...(commitAuthorOf(body.commitAuthor) ? { commitAuthor: commitAuthorOf(body.commitAuthor)! } : {}),\n };\n}\n\n/** Both halves or neither: a half-configured identity is worse than none. */\nfunction commitAuthorOf(value: { name?: unknown; email?: unknown } | undefined) {\n if (!value || typeof value.name !== \"string\" || typeof value.email !== \"string\") return undefined;\n if (!value.name || !value.email) return undefined;\n return { name: value.name, email: value.email };\n}\n\n/** Single-quote for a POSIX shell, so a name with an apostrophe still pastes. */\nexport function shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\n/** The commands that put the grant's identity on a fresh clone. */\nexport function gitConfigCommands(commitAuthor: { name: string; email: string }): string {\n return `git config user.name ${shellQuote(commitAuthor.name)} && git config user.email ${shellQuote(commitAuthor.email)}`;\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 .summary(\"Print an MCP server config for your MCP client\")\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 .summary(\"Connect this machine as a scoped agent identity\")\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 .summary(\"Inspect or manage stored credentials\")\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 .summary(\"Disconnect: revoke and clear every stored credential\")\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 .summary(\"Take a published artifact offline\")\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 .summary(\"Rename an artifact or change its visibility\")\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\")\n .summary(\"Store CLI preferences (e.g. a default API URL)\").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 { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError, validationError } from \"../api/errors.js\";\nimport { workspaceFlag } from \"../utils/workspaceFlag.js\";\n\ntype DuplicateSuccess = {\n success: true;\n sessionId: string;\n sourceSessionId: string;\n name: string;\n artifactType?: \"app\" | \"markdown\" | \"asset\";\n artifactUrl: string;\n // App copies only — a markdown or asset artifact has no Playground session.\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 message?: 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 workspaceId?: string\n): { sessionId: string; name?: string; workspaceId?: string } {\n const sessionId = parseArtifactUrl(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 {\n sessionId,\n ...(name !== undefined ? { name } : {}),\n ...(workspaceFlag(workspaceId) !== undefined ? { workspaceId } : {}),\n };\n}\n\nexport function createDuplicateCommand(): Command {\n return new Command(\"duplicate\")\n .summary(\"Copy an artifact into a new, independent one\")\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(\n \"-w, --workspace <id>\",\n \"The workspace to put the copy in (id from `anima workspaces`). Optional when you can create in \" +\n \"only one workspace; otherwise required, since there is no default\"\n )\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, opts.workspace);\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.message || 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.artifactUrl));\n if (result.playgroundUrl) {\n printKeyValue(\"Edit in Playground\", chalk.cyan.underline(result.playgroundUrl));\n }\n if (result.previewUrl) {\n printKeyValue(\"Preview\", chalk.cyan.underline(result.previewUrl));\n }\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","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { runTool } from \"../api/tool.js\";\nimport { validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `artifact-explore` MCP tool — read an artifact's files without\n * git, a shell or a clone. `revision` comes back on every response and is what\n * `anima edit --base-revision` expects.\n */\n\ntype ReadFile = {\n path: string;\n content?: string;\n totalLines?: number;\n startLine?: number;\n endLine?: number;\n truncated?: boolean;\n eol?: \"lf\" | \"crlf\";\n /** The bytes are not text, so metadata stands in for content. */\n asset?: boolean;\n size?: number;\n mime?: string;\n deferred?: boolean;\n};\n\ntype SearchMatch = { path: string; line: number; lineText: string; occurrences: number };\n\ntype CommitSummary = { revision: string; message: string; author: string; date: string };\n\ntype ExploreResult = {\n success: boolean;\n revision?: string;\n // tree\n files?: string[] | ReadFile[];\n unwritable?: Record<string, \"symlink\" | \"submodule\">;\n matchedFiles?: number;\n truncated?: boolean;\n // read\n readAt?: string;\n missingPaths?: string[];\n suggestions?: Record<string, string[]>;\n // search\n matches?: SearchMatch[];\n notSearched?: { assets?: number; excluded?: number };\n // history\n commits?: CommitSummary[];\n commit?: CommitSummary & { changedFiles?: Array<{ path: string; change: string }> };\n nextCursor?: string | null;\n};\n\nexport const exploreCommand = new Command(\"explore\")\n .summary(\"Read an artifact's files: list, search, read, history\")\n .description(\n \"Inspect an artifact's files without git: list them (--tree), search them (--search), read them (--read), or show commits (--history).\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .option(\"--tree\", \"List file paths\")\n .option(\"--search <query>\", \"Find text inside files — start here when you don't know the file\")\n .option(\"--read <paths...>\", \"Return the contents of these files\")\n .option(\"--history\", \"List commits, newest first\")\n .option(\"--path <prefix>\", \"tree/search: a literal directory prefix (not a glob)\")\n .option(\"--range <start,end>\", \"read: line window, 1-based inclusive, for a single file\")\n .option(\"--revision <rev>\", \"Look at the artifact as it was at this commit\")\n .option(\"--regex\", \"search: treat the query as a JavaScript regular expression\")\n .option(\"--case-sensitive\", \"search: match case exactly\")\n .option(\"--include-excluded\", \"tree/search: also look inside node_modules, dist and build\")\n .option(\"--limit <n>\", \"tree/search/history: maximum rows to return\")\n .option(\"--cursor <cursor>\", \"history: continue after a previous response's nextCursor\")\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 (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const sessionId = parseArtifactUrl(artifactUrl);\n const args = buildExploreArgs(sessionId, opts);\n\n const result = await runTool<ExploreResult>(\"artifact-explore\", args, { apiUrl: opts.apiUrl });\n\n if (mode === \"pretty\") {\n printExplore(args.action as string, result);\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nexport function buildExploreArgs(sessionId: string, opts: Record<string, unknown>): Record<string, unknown> {\n const chosen = [\n opts.tree ? \"tree\" : null,\n opts.search ? \"search\" : null,\n opts.read ? \"read\" : null,\n opts.history ? \"history\" : null,\n ].filter(Boolean) as string[];\n\n if (chosen.length !== 1) {\n throw validationError(\n \"Pass exactly one of --tree, --search <query>, --read <paths...> or --history. \" +\n \"Not sure which file to change? Start with --search.\"\n );\n }\n const action = chosen[0];\n\n const args: Record<string, unknown> = { sessionId, action };\n if (opts.revision) args.revision = opts.revision;\n if (opts.limit !== undefined) args.limit = parseLimit(opts.limit as string);\n\n switch (action) {\n case \"tree\":\n if (opts.path) args.path = opts.path;\n if (opts.includeExcluded) args.includeExcluded = true;\n break;\n case \"search\":\n args.query = opts.search;\n if (opts.path) args.path = opts.path;\n if (opts.regex) args.regex = true;\n if (opts.caseSensitive) args.caseSensitive = true;\n if (opts.includeExcluded) args.includeExcluded = true;\n break;\n case \"read\": {\n const paths = opts.read as string[];\n args.paths = paths;\n if (opts.range) {\n if (paths.length !== 1) {\n throw validationError(\"--range applies to a single file; pass one path to --read.\");\n }\n args.range = opts.range;\n }\n break;\n }\n case \"history\":\n if (opts.cursor) args.cursor = opts.cursor;\n break;\n }\n\n return args;\n}\n\nfunction parseLimit(value: string): number {\n const limit = Number(value);\n if (!Number.isInteger(limit) || limit < 1) {\n throw validationError(`--limit must be a positive whole number (got \"${value}\").`);\n }\n return limit;\n}\n\nfunction printExplore(action: string, result: ExploreResult): void {\n console.log();\n\n if (action === \"tree\") {\n for (const file of (result.files ?? []) as string[]) {\n const kind = result.unwritable?.[file];\n console.log(` ${file}${kind ? chalk.gray(` (${kind} — git only)`) : \"\"}`);\n }\n if (result.matchedFiles !== undefined) {\n console.log();\n console.log(chalk.gray(` ${(result.files ?? []).length} of ${result.matchedFiles} shown`));\n }\n } else if (action === \"search\") {\n for (const match of result.matches ?? []) {\n console.log(` ${chalk.cyan(match.path)}:${match.line} ${match.lineText.trim()}`);\n }\n if (!result.matches?.length) {\n console.log(\" No matches.\");\n const skipped = result.notSearched;\n if (skipped?.excluded) {\n console.log(\n chalk.yellow(\n ` ${skipped.excluded} files were skipped (node_modules, dist, build) — retry with --include-excluded.`\n )\n );\n }\n if (skipped?.assets) {\n console.log(chalk.gray(` ${skipped.assets} binary files cannot match a text query.`));\n }\n }\n } else if (action === \"read\") {\n for (const file of (result.files ?? []) as ReadFile[]) {\n console.log(chalk.bold(` ${file.path}`));\n if (file.asset) {\n console.log(chalk.gray(` binary — ${file.size ?? \"?\"} bytes, ${file.mime ?? \"unknown type\"}`));\n } else if (file.deferred) {\n console.log(chalk.yellow(\" not returned: the response ran out of budget — read it on its own\"));\n } else {\n console.log(file.content ?? \"\");\n if (file.truncated) {\n console.log(\n chalk.yellow(\n ` lines ${file.startLine}-${file.endLine} of ${file.totalLines} — read the rest with --range`\n )\n );\n }\n }\n console.log();\n }\n for (const missing of result.missingPaths ?? []) {\n const near = result.suggestions?.[missing];\n console.log(chalk.yellow(` Not found: ${missing}${near?.length ? ` — did you mean ${near.join(\", \")}?` : \"\"}`));\n }\n } else {\n const commits = result.commit ? [result.commit] : (result.commits ?? []);\n for (const commit of commits) {\n console.log(` ${chalk.yellow(commit.revision.slice(0, 10))} ${commit.message.split(\"\\n\")[0]}`);\n console.log(chalk.gray(` ${commit.author} — ${commit.date}`));\n }\n for (const changed of result.commit?.changedFiles ?? []) {\n console.log(chalk.gray(` ${changed.change.padEnd(8)} ${changed.path}`));\n }\n }\n\n if (result.truncated) {\n console.log(chalk.yellow(\" The list was capped — raise --limit to see more.\"));\n }\n if (result.revision) {\n console.log();\n console.log(chalk.gray(` revision: ${result.revision} (pass to \\`anima edit --base-revision\\`)`));\n }\n console.log();\n}\n","import { resolveAuth } from \"../auth/token.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { withMcp, type CallToolOptions } from \"./mcp.js\";\nimport { apiError } from \"./errors.js\";\n\n/**\n * Resolve credentials, run one MCP tool, and turn a `{ success: false }`\n * payload into a CliError. Tools report failure in the result rather than as a\n * transport error, and they use two shapes for it: most carry `error` as a\n * string beside `reason`, while the artifact-content tools nest\n * `{ code, message, retryable }`. Both land here so no command has to know.\n */\nexport type ToolFailure = {\n success?: boolean;\n error?: string | { code?: string; message?: string; retryable?: boolean; details?: unknown };\n reason?: string;\n nextSteps?: string | string[];\n};\n\nexport type RunToolOptions = {\n apiUrl?: string;\n figmaToken?: string;\n call?: CallToolOptions;\n};\n\nexport async function runTool<T extends ToolFailure>(\n toolName: string,\n args: Record<string, unknown>,\n options: RunToolOptions = {}\n): Promise<T> {\n const auth = await resolveAuth(options.apiUrl);\n const result = await withMcp(\n {\n apiBaseUrl: resolveApiUrl(options.apiUrl),\n token: auth.token,\n teamId: auth.teamId,\n ...(options.figmaToken ? { figmaToken: options.figmaToken } : {}),\n },\n (client) => client.callTool<T>(toolName, args, options.call)\n );\n\n if (result.success === false) {\n throw apiError(describeFailure(result), result);\n }\n return result;\n}\n\nfunction describeFailure(result: ToolFailure): string {\n const base =\n typeof result.error === \"object\" && result.error\n ? result.error.message || result.error.code || \"The tool reported a failure\"\n : result.reason || result.error || \"The tool reported a failure\";\n\n const nextSteps = Array.isArray(result.nextSteps) ? result.nextSteps.join(\"\\n\") : result.nextSteps;\n return nextSteps ? `${base}\\n${nextSteps}` : base;\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport chalk from \"chalk\";\nimport { runTool } from \"../api/tool.js\";\nimport { validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `artifact-edit` MCP tool — change an artifact's files and\n * commit them without git. Every change in one call lands as ONE commit: either\n * all of them apply or none does.\n */\n\nexport type ArtifactChange = {\n op: \"str_replace\" | \"write\" | \"delete\" | \"move\";\n path?: string;\n oldText?: string;\n newText?: string;\n replaceAll?: boolean;\n content?: string;\n encoding?: \"utf8\" | \"base64\";\n assetUploadId?: string;\n fromPath?: string;\n toPath?: string;\n};\n\ntype EditResult = {\n success: boolean;\n revision?: string;\n previousRevision?: string;\n changedFiles?: Array<{ path: string; op: string; fromPath?: string; replacements?: number }>;\n};\n\nexport const editCommand = new Command(\"edit\")\n .summary(\"Change an artifact's files and commit them\")\n .description(\n \"Change an artifact's files and commit them, without git. All changes land as one commit.\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .requiredOption(\"-m, --message <message>\", \"Commit message\")\n .option(\n \"--base-revision <rev>\",\n \"The revision the edit applies to (from `anima explore`). Defaults to the artifact's current head\"\n )\n .option(\"--changes <json>\", \"The full change list as a JSON array — the general door\")\n .option(\"--changes-file <path>\", \"Read that JSON array from a file\")\n .option(\"--write <path>\", \"Shorthand: create or replace this file\")\n .option(\"--from-file <path>\", \"--write: take the content from this local file (default: stdin is not read)\")\n .option(\"--content <text>\", \"--write: the file's complete new content\")\n .option(\"--delete <path>\", \"Shorthand: delete this file\")\n .option(\"--move <path>\", \"Shorthand: rename this file (needs --to)\")\n .option(\"--to <path>\", \"--move: the new path\")\n .option(\"--replace <path>\", \"Shorthand: swap an exact snippet in this file (needs --old and --new)\")\n .option(\"--old <text>\", \"--replace: the exact text to replace\")\n .option(\"--new <text>\", \"--replace: the replacement text\")\n .option(\"--all\", \"--replace: replace every occurrence instead of requiring exactly one\")\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 (artifactUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const sessionId = parseArtifactUrl(artifactUrl);\n const changes = buildChanges(opts);\n\n // Without an explicit base the current head is the base, the way a commit\n // applies to the checkout you have. Reading it immediately before the\n // edit keeps the conflict window small, but it IS a window: pass\n // --base-revision from an earlier explore to be told about a concurrent\n // change instead of writing over it.\n const baseRevision = opts.baseRevision ?? (await currentRevision(sessionId, opts.apiUrl));\n\n const result = await runTool<EditResult>(\n \"artifact-edit\",\n { sessionId, baseRevision, commitMessage: opts.message, changes },\n { apiUrl: opts.apiUrl }\n );\n\n if (mode === \"pretty\") {\n console.log();\n printSuccess(\"Committed.\");\n for (const changed of result.changedFiles ?? []) {\n const detail =\n changed.op === \"move\"\n ? `${changed.fromPath} → ${changed.path}`\n : changed.replacements !== undefined\n ? `${changed.path} (${changed.replacements} replaced)`\n : changed.path;\n console.log(` ${chalk.gray(changed.op.padEnd(12))} ${detail}`);\n }\n console.log();\n printKeyValue(\"Revision\", result.revision ?? \"unknown\");\n console.log();\n console.log(\" The live artifact reflects this commit.\");\n console.log();\n } else {\n outputResult(mode, result);\n }\n });\n });\n\n/** The artifact's current head, for an edit that did not name a base. */\nasync function currentRevision(sessionId: string, apiUrl?: string): Promise<string> {\n const result = await runTool<{ success: boolean; revision?: string }>(\n \"artifact-explore\",\n { sessionId, action: \"tree\", limit: 1 },\n { apiUrl }\n );\n if (!result.revision) {\n throw validationError(\n \"Could not read the artifact's current revision. Pass --base-revision from `anima explore`.\"\n );\n }\n return result.revision;\n}\n\nexport function buildChanges(opts: Record<string, unknown>): ArtifactChange[] {\n const explicit = opts.changes ?? opts.changesFile;\n const shorthands = [opts.write, opts.delete, opts.move, opts.replace].filter(Boolean);\n\n if (explicit && shorthands.length) {\n throw validationError(\n \"--changes/--changes-file already carries the whole change list; drop the --write/--delete/--move/--replace shorthand.\"\n );\n }\n\n if (explicit) {\n const raw = opts.changesFile ? readFile(opts.changesFile as string) : (opts.changes as string);\n return parseChanges(raw);\n }\n\n if (shorthands.length !== 1) {\n throw validationError(\n \"Nothing to change. Pass --changes <json> (or --changes-file), or exactly one of \" +\n \"--write <path>, --delete <path>, --move <path> --to <path>, --replace <path> --old <text> --new <text>.\"\n );\n }\n\n if (opts.write) {\n if (opts.content === undefined && !opts.fromFile) {\n throw validationError(\"--write needs the file's content: pass --content <text> or --from-file <path>.\");\n }\n if (opts.content !== undefined && opts.fromFile) {\n throw validationError(\"Pass either --content or --from-file for --write, not both.\");\n }\n return [\n {\n op: \"write\",\n path: opts.write as string,\n content: opts.fromFile ? readFile(opts.fromFile as string) : (opts.content as string),\n },\n ];\n }\n\n if (opts.delete) {\n return [{ op: \"delete\", path: opts.delete as string }];\n }\n\n if (opts.move) {\n if (!opts.to) throw validationError(\"--move needs --to <path>, the new path.\");\n return [{ op: \"move\", fromPath: opts.move as string, toPath: opts.to as string }];\n }\n\n if (opts.old === undefined || opts.new === undefined) {\n throw validationError(\"--replace needs --old <text> and --new <text>. Pass --new \\\"\\\" to delete the snippet.\");\n }\n return [\n {\n op: \"str_replace\",\n path: opts.replace as string,\n oldText: opts.old as string,\n newText: opts.new as string,\n ...(opts.all ? { replaceAll: true } : {}),\n },\n ];\n}\n\nfunction parseChanges(raw: string): ArtifactChange[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw validationError(`--changes is not valid JSON: ${(err as Error).message}`);\n }\n if (!Array.isArray(parsed) || parsed.length === 0) {\n throw validationError(\"--changes must be a non-empty JSON array of change objects.\");\n }\n return parsed as ArtifactChange[];\n}\n\nfunction readFile(path: string): string {\n try {\n return fs.readFileSync(path, \"utf-8\");\n } catch (err) {\n throw validationError(`Could not read ${path}: ${(err as Error).message}`);\n }\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport { runTool } from \"../api/tool.js\";\nimport { apiError, validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { printSuccess, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `artifact-get_asset_upload_url` MCP tool, with the upload it\n * describes carried out: stage the file, POST it, and — when `--path` says\n * where it belongs — commit it with artifact-edit in the same run.\n *\n * Files up to 256 KB need no staging at all; `anima edit` takes them inline.\n */\n\ntype AssetUploadGrant = {\n success: boolean;\n assetUploadId?: string;\n uploadUrl?: string;\n uploadFields?: Record<string, string>;\n expiresAt?: string;\n maxBytes?: number;\n};\n\ntype EditResult = { success: boolean; revision?: string };\n\nexport const uploadAssetCommand = new Command(\"upload-asset\")\n .summary(\"Add an image, font or media file over 256 KB\")\n .description(\n \"Add a large image, font or media file (over 256 KB) to an artifact: stage it, upload it, and commit it at --path.\"\n )\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID\")\n .argument(\"<file>\", \"Local file to upload\")\n .option(\n \"--path <path>\",\n \"Where the asset lands in the artifact (e.g. public/hero.png). Omit to stage only and print the assetUploadId\"\n )\n .option(\"-m, --message <message>\", \"Commit message for the write\")\n .option(\"--base-revision <rev>\", \"The revision the commit applies to. Defaults to the current head\")\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, file: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n await withCommandErrors(mode, async () => {\n const sessionId = parseArtifactUrl(artifactUrl);\n const bytes = readAsset(file);\n\n progress.start(\"Staging the upload...\");\n const grant = await runTool<AssetUploadGrant>(\n \"artifact-get_asset_upload_url\",\n { sessionId, filename: path.basename(file) },\n { apiUrl: opts.apiUrl }\n );\n if (!grant.uploadUrl || !grant.uploadFields || !grant.assetUploadId) {\n throw apiError(\"The staging response carried no upload URL.\", grant);\n }\n if (grant.maxBytes !== undefined && bytes.byteLength > grant.maxBytes) {\n throw validationError(\n `${file} is ${bytes.byteLength} bytes; the limit is ${grant.maxBytes}. Push it with git instead: anima get-git-token ${sessionId}`\n );\n }\n\n progress.update(\"Uploading...\");\n await postAsset(grant.uploadUrl, grant.uploadFields, bytes, path.basename(file));\n logEvent(\"asset_uploaded\", { sessionId, assetUploadId: grant.assetUploadId });\n\n if (!opts.path) {\n progress.succeed(\"Uploaded — not committed yet.\");\n if (mode === \"pretty\") {\n console.log();\n printKeyValue(\"assetUploadId\", grant.assetUploadId);\n console.log();\n console.log(\" Commit it where it belongs with:\");\n console.log(\n ` ${chalk.cyan(\n `anima edit ${sessionId} -m \"Add asset\" --changes '[{\"op\":\"write\",\"path\":\"public/${path.basename(file)}\",\"assetUploadId\":\"${grant.assetUploadId}\"}]'`\n )}`\n );\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n assetUploadId: grant.assetUploadId,\n expiresAt: grant.expiresAt,\n nextSteps:\n \"Call `anima edit <artifact> --changes` with a write change carrying this assetUploadId and \" +\n \"the path the file should live at. The id is single-use and expires.\",\n });\n }\n return;\n }\n\n progress.update(\"Committing...\");\n const baseRevision = opts.baseRevision ?? (await currentRevision(sessionId, opts.apiUrl));\n const result = await runTool<EditResult>(\n \"artifact-edit\",\n {\n sessionId,\n baseRevision,\n commitMessage: opts.message ?? `Add ${opts.path}`,\n changes: [{ op: \"write\", path: opts.path, assetUploadId: grant.assetUploadId }],\n },\n { apiUrl: opts.apiUrl }\n );\n\n progress.succeed(\"Uploaded and committed!\");\n if (mode === \"pretty\") {\n console.log();\n printSuccess(`${file} → ${opts.path}`);\n printKeyValue(\"Revision\", result.revision ?? \"unknown\");\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n path: opts.path,\n assetUploadId: grant.assetUploadId,\n revision: result.revision,\n });\n }\n });\n });\n\n/**\n * S3 ignores every part sent after the file, so the signature fields go first\n * and `file` goes last. A successful upload answers 204 with an empty body.\n */\nasync function postAsset(\n uploadUrl: string,\n uploadFields: Record<string, string>,\n bytes: Buffer,\n filename: string\n): Promise<void> {\n const form = new FormData();\n for (const [key, value] of Object.entries(uploadFields)) {\n form.append(key, value);\n }\n form.append(\"file\", new Blob([new Uint8Array(bytes)]), filename);\n\n const response = await fetch(uploadUrl, { method: \"POST\", body: form });\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw apiError(`Asset upload failed: HTTP ${response.status}${detail ? ` — ${detail.slice(0, 300)}` : \"\"}`);\n }\n}\n\nasync function currentRevision(sessionId: string, apiUrl?: string): Promise<string> {\n const result = await runTool<{ success: boolean; revision?: string }>(\n \"artifact-explore\",\n { sessionId, action: \"tree\", limit: 1 },\n { apiUrl }\n );\n if (!result.revision) {\n throw validationError(\"Could not read the artifact's current revision. Pass --base-revision.\");\n }\n return result.revision;\n}\n\nfunction readAsset(file: string): Buffer {\n try {\n return fs.readFileSync(file);\n } catch (err) {\n throw validationError(`Could not read ${file}: ${(err as Error).message}`);\n }\n}\n","import { Command } from \"commander\";\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, printSuccess } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { apiError, CliError, validationError } from \"../api/errors.js\";\n\ntype DeleteResult = {\n success: boolean;\n message?: string;\n code?: string;\n error?: string;\n reason?: string;\n};\n\n/** Mirror of `artifact-delete`: reversible soft deletion, never permanent deletion. */\nexport const deleteCommand = new Command(\"delete\")\n .summary(\"Delete an artifact (reversible: hidden, not erased)\")\n .description(\"Soft-delete an artifact only when explicitly requested (unpublish it first; content is retained)\")\n .argument(\"<artifactUrl>\", \"Artifact URL or session ID to soft-delete\")\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 = parseArtifactUrl(artifactUrl);\n if (!sessionId) {\n throw validationError(\"An artifact URL or session ID is required\");\n }\n\n const auth = await resolveAuth(opts.apiUrl);\n progress.start(\"Deleting artifact...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },\n (client) => client.callTool<DeleteResult>(\"artifact-delete\", { sessionId })\n );\n\n if (!result.success) {\n throw apiError(result.message || result.reason || result.error || \"Artifact deletion failed\", result);\n }\n\n progress.succeed(\"Artifact deleted\");\n if (mode === \"pretty\") {\n printSuccess(result.message || `Artifact ${sessionId} is hidden and can be restored.`);\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 const detail = err.detail as { code?: unknown } | undefined;\n const code = typeof detail?.code === \"string\" ? detail.code : err.code;\n if (mode === \"pretty\") {\n printError(code === err.code ? err.message : `${code}: ${err.message}`);\n } else {\n outputError(mode, { 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 { runTool } from \"../api/tool.js\";\nimport { validationError } from \"../api/errors.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSuccess, printInfo, printKeyValue } from \"../output/pretty.js\";\nimport { parseArtifactUrl } from \"../utils/artifactUrl.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Mirror of the `review-*` MCP tools — the change requests humans address to\n * this credential's agent on their artifacts. Nothing pushes them, so `list` is\n * how the work arrives: run it when a human says they left comments, and at the\n * start of work on an artifact you have been reviewed on before.\n */\n\ntype Reply = { author: { kind: \"user\" | \"agent\"; name: string }; body: string; closing: boolean; createdAt: string };\n\ntype ReviewComment = {\n commentId: string;\n index: number;\n body: string;\n status: \"open\" | \"resolved\" | \"dismissed\";\n /** Addressed to nobody in particular, so every agent sees it. */\n unassigned?: boolean;\n anchor?: { kind: \"dom\" | \"markdownRange\" } & Record<string, unknown>;\n replies: Reply[];\n};\n\ntype Review = {\n reviewId: string;\n sessionId: string;\n artifactUrl: string;\n isLatest: boolean;\n author: { name: string; kind: \"user\" | \"agent\" };\n resolveTrailer: string;\n comments: ReviewComment[];\n createdAt: string;\n};\n\ntype ListResult = { success: boolean; reviews?: Review[]; message?: string };\ntype ResolveResult = { success: boolean; commentId?: string; resolved?: boolean; message?: string };\ntype ReplyResult = { success: boolean; commentId?: string; replied?: boolean; message?: string };\n\nconst listSubcommand = new Command(\"list\")\n .summary(\"Read the comments addressed to you\")\n .description(\"Read the review comments addressed to you, newest artifact activity first\")\n .argument(\"[artifactUrl]\", \"Limit to one artifact; omit for every review addressed to you\")\n .option(\"--limit <n>\", \"Maximum reviews to return (1-50, default 20)\")\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 (artifactUrl: string | undefined, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const args: Record<string, unknown> = {};\n if (artifactUrl) args.sessionId = parseArtifactUrl(artifactUrl);\n if (opts.limit !== undefined) args.limit = parseLimit(opts.limit);\n\n const result = await runTool<ListResult>(\"review-list\", args, { apiUrl: opts.apiUrl });\n\n if (mode === \"pretty\") {\n printReviews(result);\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nconst resolveSubcommand = new Command(\"resolve\")\n .summary(\"Close one comment without a commit\")\n .description(\"Close one comment without a commit — for a question answered, or a change you decided against\")\n .argument(\"<commentId>\", \"Comment to close, from `anima review list`\")\n .option(\"--note <text>\", \"What to tell the reviewer as the closing message\")\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 (commentId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const result = await runTool<ResolveResult>(\n \"review-resolve\",\n { commentId, ...(opts.note ? { note: opts.note } : {}) },\n { apiUrl: opts.apiUrl }\n );\n\n if (mode === \"pretty\") {\n console.log();\n // Already closed is not a failure — a commit trailer may have closed it.\n if (result.resolved) printSuccess(result.message ?? \"Comment resolved.\");\n else printInfo(result.message ?? \"Comment was already closed.\");\n console.log();\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nconst replySubcommand = new Command(\"reply\")\n .summary(\"Answer one comment, leaving it open\")\n .description(\"Say something back on one comment and LEAVE IT OPEN — to ask, report, or say you are blocked\")\n .argument(\"<commentId>\", \"Comment to reply to, from `anima review list`\")\n .requiredOption(\"-m, --message <message>\", \"What to say to the reviewer\")\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 (commentId: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const result = await runTool<ReplyResult>(\n \"review-reply\",\n { commentId, message: opts.message },\n { apiUrl: opts.apiUrl }\n );\n\n if (mode === \"pretty\") {\n console.log();\n if (result.replied) printSuccess(result.message ?? \"Reply posted.\");\n else printInfo(result.message ?? \"The comment is closed, so nothing was posted.\");\n console.log();\n } else {\n outputResult(mode, result);\n }\n });\n });\n\nexport const reviewCommand = new Command(\"review\")\n .summary(\"Read and answer the comments humans addressed to you\")\n .description(\"Read and answer the review comments humans addressed to you (list / resolve / reply)\")\n .addCommand(listSubcommand)\n .addCommand(resolveSubcommand)\n .addCommand(replySubcommand);\n\nfunction parseLimit(value: string): number {\n const limit = Number(value);\n if (!Number.isInteger(limit) || limit < 1 || limit > 50) {\n throw validationError(`--limit must be a whole number between 1 and 50 (got \"${value}\").`);\n }\n return limit;\n}\n\nfunction printReviews(result: ListResult): void {\n const reviews = result.reviews ?? [];\n console.log();\n\n if (reviews.length === 0) {\n console.log(` ${result.message ?? \"No open reviews are addressed to you.\"}`);\n console.log();\n return;\n }\n\n for (const review of reviews) {\n console.log(` ${chalk.bold(`Review ${review.reviewId}`)} ${chalk.gray(`by ${review.author.name}`)}`);\n console.log(` ${chalk.cyan.underline(review.artifactUrl)}`);\n if (!review.isLatest) {\n console.log(\n chalk.yellow(\" The artifact moved since this was written — check the comments still apply.\")\n );\n }\n console.log();\n\n for (const comment of review.comments) {\n const marks = [\n comment.status !== \"open\" ? chalk.gray(comment.status) : null,\n comment.unassigned ? chalk.yellow(\"unassigned\") : null,\n ]\n .filter(Boolean)\n .join(\" \");\n console.log(` ${chalk.bold(`#${comment.index}`)} ${comment.body}${marks ? ` ${marks}` : \"\"}`);\n console.log(chalk.gray(` ${comment.commentId}${describeAnchor(comment)}`));\n // Replies can add to or change the request, so they are shown, not counted.\n for (const reply of comment.replies ?? []) {\n console.log(chalk.gray(` ↳ ${reply.author.name}: ${reply.body}`));\n }\n console.log();\n }\n\n printKeyValue(\"To close these in a commit\", \"\");\n for (const line of review.resolveTrailer.split(\"\\n\")) {\n console.log(` ${chalk.gray(line)}`);\n }\n console.log();\n }\n}\n\nfunction describeAnchor(comment: ReviewComment): string {\n if (!comment.anchor) return \" — about the artifact as a whole\";\n const anchor = comment.anchor as Record<string, unknown>;\n const dom = anchor.dom as Record<string, unknown> | undefined;\n const markdown = anchor.markdown as Record<string, unknown> | undefined;\n\n if (dom?.sourceFile) {\n const instances = typeof dom.instanceCount === \"number\" && dom.instanceCount > 1 ? dom.instanceCount : 0;\n return ` — ${dom.sourceFile}${dom.sourceStart ? `:${dom.sourceStart}` : \"\"}${\n instances ? ` (shared markup: ${instances} instances)` : \"\"\n }`;\n }\n if (markdown?.quote) {\n return ` — on \"${String(markdown.quote).slice(0, 60)}\"`;\n }\n return \"\";\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport { apiError, validationError } from \"../api/errors.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { printSuccess } from \"../output/pretty.js\";\nimport { version } from \"../version.js\";\nimport { withCommandErrors } from \"./runner.js\";\n\n/**\n * Install the AgentGrid guide where this agent's runtime will find it.\n *\n * The prose is NOT kept here. It is fetched from the API's `/guide.md` — the\n * door-agnostic half of the same page `/connect` serves — so there is one copy\n * to maintain and it cannot go stale in a published tarball. What this command\n * adds is the part the server cannot know: the SKILL.md envelope,\n * a connect section written for someone who already has the CLI, and a command\n * reference generated from THIS binary's own command tree, so the syntax it\n * prints is the syntax this version actually accepts.\n */\n\n/** Where the guide lives on the API, alongside `/connect`. */\nconst GUIDE_PATH = \"/guide.md\";\n\nexport function createSkillCommand(): Command {\n return new Command(\"skill\")\n .summary(\"Install the AgentGrid guide as a skill your agent can read\")\n .description(\n \"Fetch the AgentGrid agent guide and write it as a SKILL.md your runtime can load, or print \" +\n \"it to stdout. The guide comes from the API, so it stays current; the command reference is \" +\n \"generated from this CLI's own commands.\"\n )\n .argument(\n \"[path]\",\n \"Where to write the SKILL.md (e.g. .claude/skills/agentgrid/SKILL.md). Omit to print to stdout\"\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 (target: string | undefined, opts, command: Command) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n await withCommandErrors(mode, async () => {\n const apiUrl = resolveApiUrl(opts.apiUrl);\n const guide = await fetchGuide(apiUrl);\n\n // The program owns every command; reach it through this one's parent so\n // the reference lists whatever is registered, with no second list to keep.\n const program = command.parent ?? command;\n // Reference before narrative: the summaries are a map, not a tutorial, and\n // an agent that already knows AgentGrid is here for the exact syntax.\n const body = [connectSection(), commandReference(program), guide.trim(), provenance(apiUrl)].join(\n \"\\n\\n\"\n );\n const document = `${frontmatter()}\\n${body}\\n`;\n\n if (!target) {\n process.stdout.write(document.endsWith(\"\\n\") ? document : `${document}\\n`);\n return;\n }\n\n writeDocument(target, document);\n logEvent(\"skill_installed\", { path: target, bytes: document.length });\n\n if (mode === \"pretty\") {\n console.log();\n printSuccess(`Skill written to ${chalk.cyan(target)}`);\n console.log(` ${chalk.gray(`${document.length} bytes, from ${apiUrl}${GUIDE_PATH}`)}`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n path: path.resolve(target),\n bytes: document.length,\n source: `${apiUrl}${GUIDE_PATH}`,\n });\n }\n });\n });\n}\n\nexport const skillCommand = createSkillCommand();\n\nasync function fetchGuide(apiUrl: string): Promise<string> {\n const url = `${apiUrl.replace(/\\/$/, \"\")}${GUIDE_PATH}`;\n logEvent(\"skill_fetch\", { url });\n\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n throw apiError(`Could not reach ${url}: ${(err as Error).message}`);\n }\n if (response.status === 404) {\n throw apiError(\n `${url} returned 404. This API does not serve the agent guide yet — point --api-url at one that does.`\n );\n }\n if (!response.ok) {\n throw apiError(`Could not fetch the guide: HTTP ${response.status} from ${url}`);\n }\n const body = await response.text();\n if (!body.trim()) {\n throw apiError(`${url} returned an empty guide.`);\n }\n return body;\n}\n\n/**\n * Frontmatter is what makes a skill discoverable: the description decides\n * whether a runtime loads it for the task at hand, so it names the triggers\n * rather than describing the file.\n */\nfunction frontmatter(): string {\n return [\n \"---\",\n \"name: agentgrid\",\n \"description: >-\",\n \" Host, change, publish and share artifacts on AgentGrid from the command line.\",\n \" Use when asked to share an app or a document with a human, put work somewhere\",\n \" they can see it, create or edit an AgentGrid artifact, publish one to a live\",\n \" URL, or answer review comments left on one.\",\n \"---\",\n ].join(\"\\n\");\n}\n\n/**\n * The server's guide assumes a token. This is the part it cannot write: getting\n * one, for a reader who already has the CLI — so no raw-HTTP fallback, which is\n * half of what /connect spends its doors on.\n */\nfunction connectSection(): string {\n return `# AgentGrid\n\nAn **artifact** is a hosted app or document that is also a real git repository.\nEvery command below runs one AgentGrid tool for you.\n\n## Connect first\n\nYou act as a scoped agent identity a human approved and can revoke. Three doors —\nthe first is the usual one, because you arrive with something to show and they\nneed no account until they claim it:\n\n\\`\\`\\`bash\n# 1. You lead: create with no credential at all, then wait for the claim\nnpx @animaapp/cli@latest create --anonymous -t import --from ./my-project \\\\\n --client-name \"<your product name>\" --json # returns artifactUrl — send it to your human\nnpx @animaapp/cli@latest login --handoff --json # blocks until they claim; stores your credentials\n\n# 2. A human is reachable and can approve a short code\nnpx @animaapp/cli@latest login\n\n# 3. A human already sent you an invite link\nnpx @animaapp/cli@latest login --invite <url-or-code>\n\\`\\`\\`\n\nCredentials live in \\`~/.config/anima/\\` and the CLI renews them for you. Check\nwith \\`anima auth --status\\`. Every command takes \\`--json\\` for machine-readable\noutput on stdout, with progress on stderr.`;\n}\n\n/** Every registered command, straight from the program — so it cannot drift. */\nexport function commandReference(program: Command): string {\n const rows: string[] = [];\n\n for (const command of program.commands) {\n if (command.name() === \"help\") continue;\n const subcommands = command.commands.filter((sub) => sub.name() !== \"help\");\n if (subcommands.length > 0) {\n for (const sub of subcommands) {\n rows.push(row(`${command.name()} ${sub.name()}`, sub));\n }\n continue;\n }\n rows.push(row(command.name(), command));\n }\n\n return [\n \"## Command reference\",\n \"\",\n `Generated from \\`@animaapp/cli\\` ${version}, so this is what your copy accepts.`,\n \"Run `anima <command> --help` for a command's full options.\",\n \"\",\n \"| Command | What it does |\",\n \"| ------- | ------------ |\",\n ...rows,\n ].join(\"\\n\");\n}\n\nfunction row(name: string, command: Command): string {\n const usage = command.usage().replace(/\\[options\\]\\s*/, \"\").trim();\n const invocation = `anima ${name}${usage ? ` ${usage}` : \"\"}`;\n const summary = (command.summary() || command.description() || \"\").split(\"\\n\")[0];\n return `| \\`${invocation}\\` | ${escapePipes(summary)} |`;\n}\n\nconst escapePipes = (text: string): string => text.replace(/\\|/g, \"\\\\|\");\n\nfunction provenance(apiUrl: string): string {\n return `---\\n\\n_Guide fetched from ${apiUrl}${GUIDE_PATH}; command reference generated by @animaapp/cli ${version}._`;\n}\n\n/** The skill file is ours outright, so writing it is a plain overwrite. */\nfunction writeDocument(target: string, document: string): void {\n const directory = path.dirname(path.resolve(target));\n try {\n fs.mkdirSync(directory, { recursive: true });\n } catch (err) {\n throw validationError(`Could not create ${directory}: ${(err as Error).message}`);\n }\n try {\n fs.writeFileSync(target, document, \"utf-8\");\n } catch (err) {\n throw validationError(`Could not write ${target}: ${(err as Error).message}`);\n }\n}\n"],"mappings":"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","names":["Command","chalk","required","fs","path","fs","path","os","CONFIG_DIR","path","status","chalk","Command","Command","Command","chalk","Command","chalk","relative","Command","chalk","Command","chalk","Command","chalk","Command","chalk","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","chalk","Command","chalk","Command","fs","chalk","Command","chalk","path","fs","Command","fs","path","chalk","Command","path","chalk","currentRevision","fs","Command","Command","Command","chalk","Command","parseLimit","chalk","Command","fs","path","chalk","Command","program","chalk","path","fs","Command"]}