@animaapp/cli 0.3.11 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -11
- package/dist/index.js +308 -53
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/auth/store.ts","../src/api/errors.ts","../src/auth/token.ts","../src/api/mcp.ts","../src/output/log.ts","../src/version.ts","../src/output/formatter.ts","../src/output/progress.ts","../src/output/pretty.ts","../src/utils/figma.ts","../src/config/store.ts","../src/commands/publish.ts","../src/commands/codegen.ts","../src/utils/files.ts","../src/commands/getGitToken.ts","../src/utils/playgroundUrl.ts","../src/utils/gitToken.ts","../src/commands/mcpConfig.ts","../src/commands/login.ts","../src/auth/device.ts","../src/auth/invite.ts","../src/commands/auth.ts","../src/commands/logout.ts","../src/commands/config.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createCommand } from \"./commands/create.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 { configCommand } from \"./commands/config.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 `Anima CLI - Generate production-ready apps from prompts, URLs, or Figma designs.\n\nAUTHENTICATION:\n Run: npx @animaapp/cli login\n Approve in a browser on any device — the CLI receives a scoped agent token\n (stored in ~/.config/anima/). CI/automation can set ANIMA_API_TOKEN instead.\n\nTIMING (important for AI agents):\n create → 3-7 minutes (keep the default 600000ms timeout)\n publish → 1-3 minutes\n codegen → 2-5 minutes\n get-git-token → seconds\n The --timeout default is 600000ms (10 min). Do NOT reduce it.\n\nCOMMANDS:\n login Log in via the device flow (no browser needed on this machine)\n logout Clear all stored credentials from this machine\n mcp-config Print an MCP server config from stored credentials (no new login)\n create Create app from prompt, URL, or Figma design\n publish Deploy playground to live URL or npm package\n codegen Convert Figma design to code files (no playground)\n get-git-token Mint a git remote URL for a playground; clone/edit/push with git\n config Store CLI preferences (e.g. a default API URL)\n auth Inspect or manage credentials (status / figma token)\n\nEXAMPLES:\n npx @animaapp/cli login\n npx @animaapp/cli create -t p2c -p \"SaaS dashboard with sidebar and analytics\"\n npx @animaapp/cli create -t l2c -u https://stripe.com\n npx @animaapp/cli create -t f2c --file-key abc --nodes 42:15\n npx @animaapp/cli publish abc123xyz\n npx @animaapp/cli codegen --file-key abc --nodes 42:15 -o ./components\n npx @animaapp/cli get-git-token https://dev.animaapp.com/chat/abc123xyz\n\nOUTPUT: JSON to stdout when piped (for AI tools), pretty text in terminals.\n Progress is streamed to stderr via --verbose when in JSON mode.`\n )\n .version(version, \"-v, --version\");\n\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\nprogram.addCommand(createCommand);\nprogram.addCommand(publishCommand);\nprogram.addCommand(codegenCommand);\nprogram.addCommand(getGitTokenCommand);\nprogram.addCommand(mcpConfigCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(authCommand);\n\nprogram.parseAsync(process.argv).catch((err) => {\n if (err instanceof CliError) {\n if (process.stdout.isTTY) {\n console.error(err.message);\n } else {\n process.stdout.write(\n JSON.stringify({\n success: false,\n error: { code: err.code, message: err.message },\n }) + \"\\n\"\n );\n }\n process.exit(err.exitCode);\n }\n\n console.error(err);\n process.exit(1);\n});\n","import { Command } from \"commander\";\nimport { 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 { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { CreateType } from \"../api/types.js\";\n\nconst PLAYGROUND_BASE = \"https://dev.animaapp.com/chat\";\n\ntype CreateResult = {\n success: boolean;\n sessionId?: string;\n playgroundUrl?: string;\n nextSteps?: string;\n // Since the server's inline-git-token change, playground-create also mints a\n // rw git token in the same response — clone immediately, no second call.\n gitRemoteUrl?: string;\n access?: \"ro\" | \"rw\";\n expiresAt?: string;\n error?: string;\n reason?: string;\n};\n\nexport const createCommand = new Command(\"create\")\n .description(\"Create a playground: AI-generated (p2c/l2c/f2c, 3-7 min) or blank for your own code (instant)\")\n .requiredOption(\"-t, --type <type>\", \"p2c, l2c, f2c, or blank (empty playground — push your own code with get-git-token)\")\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(\"--framework <fw>\", \"html | react — the only supported frameworks (default: html)\")\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(\"--name <name>\", \"Project name (blank only)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const type = opts.type as CreateType;\n validateCreateOptions(type, opts);\n\n const auth = resolveAuth();\n const figmaToken = type === \"f2c\" ? resolveFigmaToken(opts, auth.figmaToken) : undefined;\n const args = buildCreateArgs(type, opts);\n\n progress.start(type === \"blank\" ? \"Creating blank playground...\" : `Creating ${type.toUpperCase()} playground...`);\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId, figmaToken },\n (client) =>\n client.callTool<CreateResult>(\"playground-create\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.sessionId) {\n throw apiError(result.reason || result.error || \"Generation failed\", result);\n }\n\n const playgroundUrl = result.playgroundUrl || `${PLAYGROUND_BASE}/${result.sessionId}`;\n\n progress.succeed(\"Playground created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({ sessionId: result.sessionId, playgroundUrl });\n if (result.gitRemoteUrl) {\n console.log(` git clone ${result.gitRemoteUrl}`);\n console.log();\n console.log(\n ` Add your code, commit, and git push — the playground goes live. The URL embeds a` +\n ` token${result.expiresAt ? ` (expires ${result.expiresAt})` : \"\"}; when it expires,` +\n ` run anima get-git-token ${result.sessionId} and git remote set-url origin <new url>.`\n );\n console.log();\n } else if (type === \"blank\") {\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 } else {\n outputResult(mode, {\n success: true,\n sessionId: result.sessionId,\n playgroundUrl,\n ...(result.gitRemoteUrl\n ? { gitRemoteUrl: result.gitRemoteUrl, access: result.access, expiresAt: result.expiresAt }\n : {}),\n ...(result.nextSteps ? { nextSteps: result.nextSteps } : {}),\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\nfunction validateCreateOptions(type: CreateType, opts: Record<string, string>): void {\n if (![\"p2c\", \"l2c\", \"f2c\", \"blank\"].includes(type)) {\n throw validationError(`Invalid type \"${type}\". Must be p2c, l2c, f2c, or blank.`);\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}\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 // Always sent: the server requires framework for blank (declare what\n // you'll push), and html is the default for every type — aligned with the\n // MCP playground-create surface. Only html and react are supported.\n const framework = opts.framework ?? \"html\";\n if (type === \"blank\") {\n return { type, framework, ...(opts.name ? { name: opts.name } : {}) };\n }\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 args: Record<string, unknown> = {\n type,\n framework,\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n switch (type) {\n case \"p2c\":\n args.prompt = opts.prompt;\n if (opts.guidelines) args.guidelines = opts.guidelines;\n break;\n case \"l2c\":\n args.url = opts.url;\n break;\n case \"f2c\": {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n args.fileKey = fileKey;\n args.nodesId = nodesId;\n break;\n }\n }\n\n return args;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".config\", \"anima\");\nconst CREDENTIALS_FILE = path.join(CONFIG_DIR, \"credentials.json\");\n\ntype Credentials = {\n token: string;\n teamId?: string;\n figmaToken?: string;\n // Set by the device login: a scoped, revocable AGENT token — never to be\n // confused with a personal API token (which carries the user's full\n // authority and is not governed by workspace scopes).\n tokenType?: \"agent\" | \"personal\";\n agentId?: string;\n expiresAt?: string; // ISO — agent tokens expire (~7 days); re-run the login\n};\n\nexport function readCredentials(): Credentials | null {\n try {\n if (!fs.existsSync(CREDENTIALS_FILE)) return null;\n const content = fs.readFileSync(CREDENTIALS_FILE, \"utf-8\");\n const parsed = JSON.parse(content);\n if (!parsed.token) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nexport function writeCredentials(credentials: Partial<Credentials>): void {\n // Merge with existing credentials so we can update fields independently\n const existing = readCredentials() ?? {};\n const merged = { ...existing, ...credentials };\n\n // Remove undefined values\n for (const key of Object.keys(merged) as (keyof Credentials)[]) {\n if (merged[key] === undefined) delete merged[key];\n }\n\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(\n CREDENTIALS_FILE,\n JSON.stringify(merged, null, 2) + \"\\n\",\n { mode: 0o600 }\n );\n}\n\nexport function deleteCredentials(): boolean {\n try {\n if (fs.existsSync(CREDENTIALS_FILE)) {\n fs.unlinkSync(CREDENTIALS_FILE);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Full logout: remove every stored token (all live in credentials.json) and\n * the config directory itself when nothing else is left in it. Returns whether\n * any credentials were present.\n */\nexport function clearStorage(): boolean {\n const had = deleteCredentials();\n try {\n if (fs.existsSync(CONFIG_DIR) && fs.readdirSync(CONFIG_DIR).length === 0) {\n fs.rmdirSync(CONFIG_DIR);\n }\n } catch {\n /* leaving an empty dir behind is harmless */\n }\n return had;\n}\n\nexport function getCredentialsPath(): string {\n return CREDENTIALS_FILE;\n}\n\n/**\n * Extract the defaultTeamId from a JWT token payload (base64-decoded, no verification).\n * Returns undefined if extraction fails.\n */\nexport function extractTeamIdFromJWT(token: string): string | undefined {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf-8\")\n );\n return payload.defaultTeamId ?? undefined;\n } catch {\n return undefined;\n }\n}\n","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 { readCredentials } from \"./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\" | \"personal\";\n};\n\nexport function resolveAuth(): ResolvedAuth {\n const creds = readCredentials();\n\n // 1. Environment variable (primary — what AI tools use)\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 || creds?.figmaToken,\n source: \"env\",\n };\n }\n\n // 2. Stored credentials file\n if (creds) {\n // Agent tokens expire (~7 days); renewal is a fresh device login, which\n // reconnects to the same agent when the same name is approved.\n if (creds.tokenType === \"agent\" && creds.expiresAt && new Date(creds.expiresAt) <= new Date()) {\n throw authError(\"Your agent token has expired. Run: anima login\");\n }\n return {\n token: creds.token,\n teamId: creds.teamId,\n figmaToken: process.env.FIGMA_TOKEN || creds.figmaToken,\n source: \"file\",\n tokenType: creds.tokenType,\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 Anima 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 Anima MCP endpoint: ${message}`,\n 1\n );\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 { 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 this.#spinner = ora(message).start();\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"started\", message }) + \"\\n\");\n }\n }\n\n update(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.text = `${message} ${elapsed}`;\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"progress\", message }) + \"\\n\");\n }\n }\n\n succeed(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.succeed(`${message} ${elapsed}`);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"done\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n fail(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n this.#spinner.fail(message);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"error\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n #elapsed(): string {\n const ms = Date.now() - this.#startTime;\n const seconds = Math.floor(ms / 1000);\n if (seconds < 60) return `(${seconds}s)`;\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `(${minutes}m ${secs}s)`;\n }\n}\n","import chalk from \"chalk\";\n\nexport function printSuccess(message: string): void {\n console.log(chalk.green(\"✓\") + \" \" + message);\n}\n\nexport function printError(message: string): void {\n console.error(chalk.red(\"✗\") + \" \" + message);\n}\n\nexport function printInfo(message: string): void {\n console.log(chalk.blue(\"ℹ\") + \" \" + message);\n}\n\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(\"⚠\") + \" \" + message);\n}\n\nexport function printKeyValue(key: string, value: string): void {\n console.log(` ${chalk.gray(key + \":\")} ${value}`);\n}\n\nexport function printSessionResult(result: {\n sessionId: string;\n playgroundUrl?: string;\n tokenUsage?: number;\n}): void {\n console.log();\n printSuccess(\"Playground created successfully!\");\n printKeyValue(\"Session ID\", result.sessionId);\n if (result.playgroundUrl) {\n printKeyValue(\"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: {\n url?: string;\n packageUrl?: string;\n packageName?: string;\n packageVersion?: string;\n}): void {\n console.log();\n printSuccess(\"Published successfully!\");\n if (result.url) {\n printKeyValue(\"Live URL\", chalk.cyan.underline(result.url));\n }\n if (result.packageName) {\n printKeyValue(\"Package\", result.packageName);\n printKeyValue(\"Version\", result.packageVersion ?? \"\");\n if (result.packageUrl) {\n printKeyValue(\"URL\", chalk.cyan.underline(result.packageUrl));\n }\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 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://public-api.animaapp.com\";\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 { 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 { validationError, CliError } from \"../api/errors.js\";\n\nexport const publishCommand = new Command(\"publish\")\n .description(\"Deploy playground to live URL or npm package (1-3 min)\")\n .argument(\"<sessionId>\", \"Session ID from create command\")\n .option(\"--mode <mode>\", \"webapp | designSystem\", \"webapp\")\n .option(\"--package-name <name>\", \"NPM package name (designSystem mode)\")\n .option(\"--package-version <version>\", \"NPM package version (designSystem mode)\")\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 (![\"webapp\", \"designSystem\"].includes(opts.mode)) {\n throw validationError(\n `Invalid mode \"${opts.mode}\". Must be webapp or designSystem.`\n );\n }\n\n if (opts.mode === \"designSystem\" && !opts.packageName) {\n throw validationError(\"--package-name is required for designSystem mode\");\n }\n\n const auth = resolveAuth();\n\n const args: Record<string, unknown> = {\n sessionId,\n mode: opts.mode,\n };\n if (opts.packageName) args.packageName = opts.packageName;\n if (opts.packageVersion) args.packageVersion = opts.packageVersion;\n\n progress.start(`Publishing as ${opts.mode}...`);\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>>(\"playground-publish\", args, {\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({\n url: result.liveUrl as string | undefined,\n packageUrl: result.packageUrl as string | undefined,\n packageName: result.packageName as string | undefined,\n packageVersion: result.packageVersion as string | undefined,\n });\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n ...(result.liveUrl ? { liveUrl: result.liveUrl, subdomain: result.subdomain } : {}),\n ...(result.packageName\n ? {\n packageName: result.packageName,\n packageVersion: result.packageVersion,\n packageUrl: result.packageUrl,\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 { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printFilesWritten } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { writeFilesToDisk } from \"../utils/files.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\ntype CodegenResult = {\n success: boolean;\n sessionId?: string;\n files?: AnimaFiles;\n tokenUsage?: number;\n error?: string;\n reason?: string;\n};\n\nexport const codegenCommand = new Command(\"codegen\")\n .description(\"Convert Figma design to code files (no playground)\")\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 = resolveAuth();\n\n // Resolve Figma token: flag > env var > stored credentials > error.\n // Sent via the X-Figma-Token header; the tool reads it from the header.\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || auth.figmaToken;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n\n // Default language to typescript when framework is react.\n const language = opts.language ?? (opts.framework === \"react\" ? \"typescript\" : undefined);\n\n const args: Record<string, unknown> = {\n fileKey,\n nodesId,\n framework: opts.framework,\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n progress.start(\"Generating code from Figma...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId, figmaToken },\n (client) =>\n client.callTool<CodegenResult>(\"codegen-figma_to_code\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.files) {\n throw apiError(result.reason || result.error || \"Code generation failed\", result);\n }\n\n const count = writeFilesToDisk(result.files, opts.output);\n\n progress.succeed(`Generated ${count} files`);\n\n if (mode === \"pretty\") {\n printFilesWritten(opts.output, count);\n } else {\n outputResult(mode, {\n success: true,\n output: opts.output,\n fileCount: count,\n sessionId: result.sessionId,\n tokenUsage: result.tokenUsage,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\n/**\n * Write generated files to disk.\n * Handles both code (text) and binary (base64-encoded) files.\n */\nexport function writeFilesToDisk(\n files: AnimaFiles,\n outputDir: string\n): number {\n // Create output directory\n fs.mkdirSync(outputDir, { recursive: true });\n\n let count = 0;\n\n const resolvedOutput = path.resolve(outputDir);\n\n for (const [filePath, fileContent] of Object.entries(files)) {\n const fullPath = path.resolve(outputDir, filePath);\n\n if (!fullPath.startsWith(resolvedOutput + path.sep)) {\n throw new Error(`Path traversal detected: ${filePath}`);\n }\n\n // Create parent directories\n const dirPath = path.dirname(fullPath);\n fs.mkdirSync(dirPath, { recursive: true });\n\n if (fileContent.isBinary) {\n const buffer = Buffer.from(fileContent.content, \"base64\");\n fs.writeFileSync(fullPath, buffer);\n } else {\n fs.writeFileSync(fullPath, fileContent.content, \"utf-8\");\n }\n\n count++;\n }\n\n return count;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { parsePlaygroundUrl } from \"../utils/playgroundUrl.js\";\nimport { parseGitTokenResponse } from \"../utils/gitToken.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `project-get_git_token` MCP tool — git is the only content\n * plane for playground 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 playground\n * git remote set-url origin <url> # after expiry: point the clone at a fresh URL\n *\n * The token expires within an hour and cannot be renewed — re-run this command\n * for a fresh URL.\n */\nexport const getGitTokenCommand = new Command(\"get-git-token\")\n .description(\"Mint a short-lived git remote URL for a playground (clone/push with git)\")\n .argument(\"<playgroundUrl>\", \"Playground 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 (playgroundUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const sessionId = parsePlaygroundUrl(playgroundUrl);\n const auth = resolveAuth();\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>(\"project-get_git_token\", { sessionId })\n );\n\n const grant = parseGitTokenResponse(response);\n logEvent(\"git_token_granted\", { sessionId, access: grant.access, expiresAt: grant.expiresAt });\n\n progress.succeed(`Git access granted (${grant.access === \"rw\" ? \"read-write\" : \"read-only\"})`);\n\n if (mode === \"pretty\") {\n console.log();\n console.log(` ${chalk.cyan(`git clone ${grant.gitRemoteUrl}`)}`);\n console.log();\n if (grant.access === \"rw\") {\n console.log(\" Commit and push to update the live playground.\");\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 playground.\");\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n gitRemoteUrl: grant.gitRemoteUrl,\n access: grant.access,\n expiresAt: grant.expiresAt,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","/**\n * Parse a playground URL to extract the session ID.\n * Supported formats:\n * - https://dev.animaapp.com/chat/SESSION_ID\n * - Just a session ID string\n */\nexport function parsePlaygroundUrl(input: string): string {\n if (!input.includes(\"/\")) {\n return input;\n }\n\n try {\n const url = new URL(input);\n const parts = url.pathname.split(\"/\").filter(Boolean);\n // Expected: /chat/SESSION_ID\n const chatIndex = parts.indexOf(\"chat\");\n if (chatIndex !== -1 && chatIndex + 1 < parts.length) {\n return parts[chatIndex + 1];\n }\n // Fallback: last path segment\n return parts[parts.length - 1];\n } catch {\n // Not a URL, treat as session ID\n return input;\n }\n}\n","import { apiError } from \"../api/errors.js\";\n\n/**\n * Parsed outcome of the `project-get_git_token` MCP tool.\n *\n * The tool returns JSON: `{ success, gitRemoteUrl, access, expiresAt }` on a\n * grant, or `{ success: false, error, reason }` on a denial. The MCP client\n * (api/mcp.ts) already JSON-parses tool text, so this receives the parsed\n * object — a string only arrives if that parse failed. The clone URL embeds a\n * short-lived access token scoped to the one playground.\n */\nexport type GitTokenGrant = {\n gitRemoteUrl: string;\n access: \"ro\" | \"rw\";\n expiresAt?: string;\n};\n\nfunction preview(payload: unknown): string {\n const text = typeof payload === \"string\" ? payload : JSON.stringify(payload);\n return (text ?? String(payload)).slice(0, 200);\n}\n\nexport function parseGitTokenResponse(payload: unknown): GitTokenGrant {\n let value = payload;\n if (typeof value === \"string\") {\n try {\n value = JSON.parse(value);\n } catch {\n throw apiError(`Unexpected response from project-get_git_token: ${preview(payload)}`);\n }\n }\n\n if (value === null || typeof value !== \"object\") {\n throw apiError(`Unexpected response from project-get_git_token: ${preview(payload)}`);\n }\n\n const body = value as {\n success?: boolean;\n error?: string;\n reason?: string;\n gitRemoteUrl?: string;\n access?: string;\n expiresAt?: string;\n };\n\n if (body.success === false) {\n throw apiError(`Git access ${body.error ?? \"denied\"}: ${(body.reason ?? \"\").trim()}`);\n }\n\n if (!body.gitRemoteUrl) {\n throw apiError(`Unexpected response from project-get_git_token: ${preview(payload)}`);\n }\n\n return {\n gitRemoteUrl: body.gitRemoteUrl,\n access: body.access === \"rw\" ? \"rw\" : \"ro\",\n expiresAt: body.expiresAt,\n };\n}\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { readCredentials } from \"../auth/store.js\";\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 from EXISTING credentials — no network, no new\n * device flow. This is the \"I'm already logged in, give me my config\" command\n * the /connect guide's Step 2 points at; `login --print-mcp-config` remains\n * the one-shot variant (fresh login, then print).\n */\nexport const mcpConfigCommand = new Command(\"mcp-config\")\n .description(\"Print an MCP server config from your stored credentials (run `login` first)\")\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 // Resolution + expiry checks live in resolveAuth: env token → stored\n // credentials (expired agent token → clear \"run anima login\" error).\n const auth = resolveAuth();\n const creds = readCredentials();\n const expiresAt = auth.source === \"env\" ? undefined : creds?.expiresAt;\n\n const mcpConfig = buildMcpConfig(resolveApiUrl(opts.apiUrl), auth.token);\n\n if (mode === \"pretty\") {\n printInfo(\"MCP server config (add to your MCP client; the token is a secret):\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n console.log();\n if (expiresAt) {\n printInfo(`Token expires ${expiresAt} — run \\`anima login\\` then \\`anima mcp-config\\` to refresh.`);\n }\n } else {\n outputResult(mode, {\n success: true,\n mcpConfig,\n ...(expiresAt ? { expiresAt } : {}),\n ...(creds?.agentId && auth.source !== \"env\" ? { agentId: creds.agentId } : {}),\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","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { loginWithDeviceFlow } from \"../auth/device.js\";\nimport { loginWithInvite, parseInvite } from \"../auth/invite.js\";\nimport { getCredentialsPath } from \"../auth/store.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { resolveApiUrl, setConfig, readConfig } from \"../config/store.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printSuccess, printError, printKeyValue, printInfo } from \"../output/pretty.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * `anima login` — connect this machine as a governed agent.\n *\n * Two doors, one credential store:\n * - Default: the OAuth device flow. The command prints a short code and a\n * verification URL; a human approves on any device — choosing which\n * workspaces and capabilities this agent gets — and the CLI picks up its\n * scoped token automatically.\n * - `--invite <url-or-code>`: redeem a pre-approved invite (the human already\n * consented in-app when minting it) — a single exchange, no human step and\n * no browser.\n * Either way the token expires after ~7 days; logging in again with the same\n * agent name reconnects to the same agent identity.\n */\nexport const loginCommand = new Command(\"login\")\n .description(\"Log in via the device flow, or redeem a pre-approved invite with --invite\")\n .option(\"--invite <url-or-code>\", \"Redeem an invite link (…/invite/<code>.md) or bare code — no approval step\")\n .option(\"--client-name <name>\", \"How this CLI appears on the consent screen\", \"Anima 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 (includes the token) to paste into an MCP-capable agent\"\n )\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n if (opts.invite) {\n // The invite URL was minted on the API the human used, so its origin is\n // the right base unless the caller explicitly overrides it.\n const inviteOrigin = parseInvite(opts.invite).origin;\n const apiUrl = opts.apiUrl ? resolveApiUrl(opts.apiUrl) : (inviteOrigin ?? resolveApiUrl());\n\n try {\n const result = await loginWithInvite({ apiUrl, invite: opts.invite });\n // Persist the origin the invite was redeemed on: the token is only\n // valid THERE, so later commands (get-git-token, mcp-config, …) must\n // default to it instead of the built-in API URL.\n if (inviteOrigin && readConfig().apiUrl !== apiUrl) {\n setConfig(\"api-url\", apiUrl);\n }\n const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl, result.token) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n if (result.agentId) printKeyValue(\"Agent\", result.agentId);\n if (result.teamId) printKeyValue(\"Team ID\", result.teamId);\n if (result.expiresAt) 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 (token expires ~7 days — a fresh invite renews it):\");\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, result.token) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n if (result.agentId) printKeyValue(\"Agent\", result.agentId);\n if (result.teamId) printKeyValue(\"Team ID\", result.teamId);\n if (result.expiresAt) 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 (token expires ~7 days — re-run `anima login` to refresh):\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"logged_in\",\n tokenType: \"agent\",\n agentId: result.agentId,\n teamId: result.teamId,\n expiresAt: result.expiresAt,\n ...(mcpConfig ? { mcpConfig } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\n/**\n * A remote MCP server entry an MCP-capable agent can add to talk to Anima\n * directly (no CLI in the loop). Exact keys vary by client; this is the common\n * `mcpServers` shape with a bearer header. The URL honors --api-url/config so a\n * local login yields a local config.\n */\nexport function buildMcpConfig(apiUrl: string, token: string) {\n return {\n mcpServers: {\n anima: {\n type: \"http\",\n url: `${apiUrl.replace(/\\/$/, \"\")}/v1/mcp`,\n headers: { Authorization: `Bearer ${token}` },\n },\n },\n };\n}\n","import { writeCredentials } from \"./store.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. It expires after ~7 days; renewal is simply running\n * the flow again (re-approval reconnects to the same agent when the same\n * agent name is kept).\n */\n\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst DEFAULT_CLIENT_NAME = \"Anima CLI\";\n\nexport type DeviceVerificationInfo = {\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresInSeconds: number;\n};\n\nexport type DeviceLoginResult = {\n token: string;\n teamId?: string;\n agentId?: string;\n expiresAt?: string;\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\n/** Decode a JWT payload without verification (display/bookkeeping only). */\nfunction 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\nexport async function loginWithDeviceFlow(options: DeviceLoginOptions): Promise<DeviceLoginResult> {\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 token = body.access_token;\n const claims = decodeJwtPayload(token);\n const result: DeviceLoginResult = {\n token,\n teamId: typeof claims?.team_id === \"string\" ? claims.team_id : undefined,\n agentId: typeof claims?.agent_id === \"string\" ? claims.agent_id : undefined,\n expiresAt:\n typeof claims?.exp === \"number\" ? new Date(claims.exp * 1000).toISOString() : undefined,\n };\n\n writeCredentials({\n token: result.token,\n teamId: result.teamId,\n tokenType: \"agent\",\n agentId: result.agentId,\n expiresAt: result.expiresAt,\n });\n\n return result;\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 { writeCredentials } from \"./store.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://public-api.animaapp.com/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\nexport type InviteLoginResult = {\n token: string;\n teamId?: string;\n agentId?: string;\n expiresAt?: string;\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\n/** Decode a JWT payload without verification (display/bookkeeping only). */\nfunction 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\nexport async function loginWithInvite(options: InviteLoginOptions): Promise<InviteLoginResult> {\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 token = body.access_token;\n const claims = decodeJwtPayload(token);\n const result: InviteLoginResult = {\n token,\n teamId: typeof claims?.team_id === \"string\" ? claims.team_id : undefined,\n agentId: typeof claims?.agent_id === \"string\" ? claims.agent_id : undefined,\n expiresAt: typeof claims?.exp === \"number\" ? new Date(claims.exp * 1000).toISOString() : undefined,\n };\n\n // Same credential shape as the device login — the whole CLI surface\n // (logout, mcp-config, get-git-token, …) works identically from here.\n writeCredentials({\n token: result.token,\n teamId: result.teamId,\n tokenType: \"agent\",\n agentId: result.agentId,\n expiresAt: result.expiresAt,\n });\n\n return result;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { writeCredentials, clearStorage, readCredentials, getCredentialsPath, extractTeamIdFromJWT } from \"../auth/store.js\";\nimport { resolveAuth } from \"../auth/token.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://public-api.animaapp.com\";\n\nexport const authCommand = new Command(\"auth\")\n .description(\"Manage authentication\")\n .option(\"--token <token>\", \"Store Anima 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: Record<string, string> = {};\n\n if (opts.token) {\n toSave.token = opts.token;\n toSave.teamId = opts.teamId ?? extractTeamIdFromJWT(opts.token) ?? \"\";\n }\n if (opts.figmaToken) {\n toSave.figmaToken = opts.figmaToken;\n }\n\n writeCredentials(toSave);\n\n if (mode === \"pretty\") {\n printSuccess(\"Credentials saved to \" + getCredentialsPath());\n if (opts.token) {\n printKeyValue(\"Anima 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 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 });\n }\n return;\n }\n\n if (opts.status) {\n try {\n const auth = resolveAuth();\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(\"Anima token\", auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4));\n printKeyValue(\"Token type\", auth.tokenType === \"agent\" ? \"agent (scoped, revocable)\" : \"personal/API\");\n if (creds?.tokenType === \"agent\" && creds.expiresAt) printKeyValue(\"Expires\", creds.expiresAt);\n if (auth.teamId) printKeyValue(\"Team ID\", auth.teamId);\n printKeyValue(\"Figma token\", hasFigma ? \"configured\" : \"not set (needed for codegen/f2c)\");\n } else {\n outputResult(mode, {\n success: true,\n source: auth.source,\n tokenType: auth.tokenType ?? \"personal\",\n tokenPreview: auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4),\n teamId: auth.teamId,\n expiresAt: creds?.tokenType === \"agent\" ? creds.expiresAt : undefined,\n figmaToken: hasFigma,\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n } else {\n throw err;\n }\n }\n return;\n }\n\n // No flag: show help\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"Auth commands:\");\n console.log(` ${chalk.cyan(\"anima login\")} Log in (device flow — approve on any browser)`);\n console.log(` ${chalk.cyan(\"anima logout\")} Clear all credentials`);\n console.log(` ${chalk.cyan(\"anima auth --status\")} Check auth status`);\n console.log(` ${chalk.cyan(\"anima auth --figma-token <T>\")} Save Figma token (needed for codegen/f2c)`);\n console.log();\n console.log(` Figma token: ${chalk.cyan.underline(\"https://www.figma.com\")} > Settings > Personal access tokens`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n message: \"Run `anima login`, or use --status / --logout / --figma-token\",\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { clearStorage, getCredentialsPath } from \"../auth/store.js\";\nimport { deleteConfig } 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. Note: this only forgets the token locally; to actually disable an\n * agent, revoke it from your team settings.\n */\nexport const logoutCommand = new Command(\"logout\")\n .description(\"Clear all stored credentials (Anima + Figma tokens) from this machine\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const mode = detectOutputMode(opts);\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 } else {\n printInfo(\"No stored credentials found\");\n }\n } else {\n outputResult(mode, { success: true, action: \"logged_out\", hadCredentials });\n }\n });\n","import { Command } from \"commander\";\nimport {\n readConfig,\n setConfig,\n unsetConfig,\n getConfigPath,\n isConfigKey,\n configKeys,\n CONFIG_KEYS,\n resolveApiUrl,\n DEFAULT_API_URL,\n type ConfigKey,\n} from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { printSuccess, printInfo, printKeyValue } from \"../output/pretty.js\";\nimport { validationError } from \"../api/errors.js\";\n\n/**\n * `anima config` — store non-secret CLI preferences in\n * ~/.config/anima/config.json so you don't have to pass flags like `--api-url`\n * every time. Resolution precedence for the API URL: flag → ANIMA_API_URL env →\n * stored config → default.\n *\n * anima config set api-url http://localhost:3789\n * anima config get api-url\n * anima config list\n * anima config unset api-url\n */\nexport const configCommand = new Command(\"config\").description(\n `Store CLI preferences (keys: ${configKeys().join(\", \")})`\n);\n\nconfigCommand\n .command(\"set <key> <value>\")\n .description(\"Set a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, value: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n if (key === \"api-url\") assertUrl(value);\n setConfig(key, value);\n\n if (mode === \"pretty\") printSuccess(`Set ${key} = ${value}`);\n else outputResult(mode, { success: true, action: \"config_set\", key, value });\n });\n\nconfigCommand\n .command(\"get <key>\")\n .description(\"Print a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const value = readConfig()[CONFIG_KEYS[key]];\n\n if (mode === \"pretty\") {\n if (value) console.log(value);\n else printInfo(`${key} is not set`);\n } else {\n outputResult(mode, { success: true, key, value: value ?? null });\n }\n });\n\nconfigCommand\n .command(\"list\")\n .alias(\"ls\")\n .description(\"Show all config values and where the API URL resolves from\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const mode = detectOutputMode(opts);\n const config = readConfig();\n const resolvedApiUrl = resolveApiUrl();\n\n if (mode === \"pretty\") {\n printInfo(\"Config: \" + getConfigPath());\n printKeyValue(\"api-url\", config.apiUrl ?? `(default) ${DEFAULT_API_URL}`);\n if (process.env.ANIMA_API_URL) {\n printInfo(`ANIMA_API_URL env is set — it overrides config (effective: ${resolvedApiUrl})`);\n }\n } else {\n outputResult(mode, {\n success: true,\n path: getConfigPath(),\n config,\n resolved: { apiUrl: resolvedApiUrl },\n });\n }\n });\n\nconfigCommand\n .command(\"unset <key>\")\n .description(\"Remove a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const removed = unsetConfig(key);\n\n if (mode === \"pretty\") {\n if (removed) printSuccess(`Unset ${key}`);\n else printInfo(`${key} was not set`);\n } else {\n outputResult(mode, { success: true, action: \"config_unset\", key, removed });\n }\n });\n\nfunction assertKey(key: string): asserts key is ConfigKey {\n if (!isConfigKey(key)) {\n throw validationError(`Unknown config key \"${key}\". Valid keys: ${configKeys().join(\", \")}`);\n }\n}\n\nfunction assertUrl(value: string): void {\n try {\n new URL(value);\n } catch {\n throw validationError(`\"${value}\" is not a valid URL`);\n }\n}\n"],"mappings":"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","names":["Command","fs","path","fs","path","os","CONFIG_DIR","Command","Command","Command","fs","path","Command","Command","chalk","Command","chalk","Command","Command","chalk","decodeJwtPayload","Command","apiUrl","chalk","Command","Command","chalk","DEFAULT_API_URL","Command","chalk","Command","Command","Command","Command","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/auth/store.ts","../src/api/errors.ts","../src/auth/token.ts","../src/api/mcp.ts","../src/output/log.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/config/store.ts","../src/commands/publish.ts","../src/commands/codegen.ts","../src/utils/files.ts","../src/commands/getGitToken.ts","../src/utils/playgroundUrl.ts","../src/utils/gitToken.ts","../src/commands/mcpConfig.ts","../src/commands/login.ts","../src/auth/device.ts","../src/auth/invite.ts","../src/commands/auth.ts","../src/commands/logout.ts","../src/commands/unpublish.ts","../src/commands/update.ts","../src/commands/config.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createCommand } from \"./commands/create.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 { 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 `Anima CLI — host, edit, and publish your work on Anima. Every playground is a\nreal git repository; each command runs an Anima tool for you.\n\nTHE MAIN FLOW (build something and put it on Anima):\n 1. npx @animaapp/cli login # once; a human approves\n 2. npx @animaapp/cli create -t import --from ./my-project # your code → a live playground\n (or: create -t empty --framework html — an empty repo you push to)\n 3. The response includes a rw gitRemoteUrl — git clone, edit, commit, push:\n every push updates the live playground.\n 4. Share the playgroundUrl with your human. That IS sharing — the playground\n is visible at its URL. Do NOT run publish unless the human explicitly\n asked for a public site; offer it as a follow-up question instead.\n\nAUTHENTICATION:\n npx @animaapp/cli login # device flow — a human approves on any device\n npx @animaapp/cli login --invite <url> # redeem a pre-approved invite link (no approval step)\n Credentials live in ~/.config/anima/; logout removes everything.\n\nTIMING (important for AI agents):\n create -t empty|import → seconds\n create -t p2c|l2c|f2c → 3-7 minutes AI generation (keep the default 600000ms timeout)\n publish/unpublish → 1-3 minutes\n get-git-token / update → seconds\n\nCOMMANDS:\n login Connect (device flow, or --invite to redeem an invite link)\n logout Full local reset — clears credentials and CLI config\n create Make a playground: import your code, empty repo, or AI-generated (p2c/l2c/f2c)\n get-git-token Fresh git access to an existing playground (or after token expiry)\n update Rename a playground or set visibility public/private (metadata only)\n publish Deploy to a public live URL — ONLY when the human asked for it\n unpublish Take a published playground offline (inverse of publish)\n mcp-config Print an MCP server config from stored credentials (no new login)\n codegen Convert Figma design to local code files (no playground)\n config Store CLI preferences (e.g. a default API URL)\n auth Inspect or manage credentials (status / figma token)\n\nEXAMPLES (headless flow):\n npx @animaapp/cli login --invite https://public-api.animaapp.com/invite/<code>.md\n npx @animaapp/cli create -t import --from ./my-project\n npx @animaapp/cli create -t empty --framework react --name \"My app\"\n npx @animaapp/cli get-git-token <sessionId>\n npx @animaapp/cli update <sessionId> --privacy public\n npx @animaapp/cli publish <sessionId> # only on explicit request\n npx @animaapp/cli unpublish <sessionId>\n\nOUTPUT: JSON to stdout when piped (for AI tools), pretty text in terminals.\n Progress is streamed to stderr via --verbose when in JSON mode.`\n )\n .version(version, \"-v, --version\");\n\nprogram.addCommand(loginCommand);\nprogram.addCommand(logoutCommand);\nprogram.addCommand(createCommand);\nprogram.addCommand(publishCommand);\nprogram.addCommand(unpublishCommand);\nprogram.addCommand(updateCommand);\nprogram.addCommand(codegenCommand);\nprogram.addCommand(getGitTokenCommand);\nprogram.addCommand(mcpConfigCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(authCommand);\n\nprogram.parseAsync(process.argv).catch((err) => {\n if (err instanceof CliError) {\n if (process.stdout.isTTY) {\n console.error(err.message);\n } else {\n process.stdout.write(\n JSON.stringify({\n success: false,\n error: { code: err.code, message: err.message },\n }) + \"\\n\"\n );\n }\n process.exit(err.exitCode);\n }\n\n console.error(err);\n process.exit(1);\n});\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printSessionResult } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { collectProjectSource } from \"../utils/projectSource.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { CreateType } from \"../api/types.js\";\n\nconst PLAYGROUND_BASE = \"https://dev.animaapp.com/chat\";\n\ntype CreateResult = {\n success: boolean;\n sessionId?: string;\n playgroundUrl?: string;\n // Minted with the playground, same shape as project-get_git_token.\n gitRemoteUrl?: string;\n access?: \"ro\" | \"rw\";\n expiresAt?: string;\n // Own-code only\n framework?: \"html\" | \"react\";\n fileCount?: number;\n skippedFiles?: string[];\n notes?: string;\n nextSteps?: string;\n error?: string;\n reason?: string;\n};\n\ntype ZipUploadGrant = {\n success: boolean;\n zipUploadId?: string;\n uploadUrl?: string;\n uploadUrlExpiresAt?: string;\n nextSteps?: string | string[];\n error?: string;\n reason?: string;\n};\n\nexport const createCommand = new Command(\"create\")\n .description(\n \"Create a playground: AI-generated (p2c/l2c/f2c, 3-7 min), empty for code you'll push (instant), or import your existing code (instant)\"\n )\n .requiredOption(\n \"-t, --type <type>\",\n \"p2c, l2c, f2c, empty (empty repo you push to), or import (create FROM your code — use --from)\"\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(\"--name <name>\", \"Project name (empty/import only)\")\n .option(\"--from <path>\", \"Folder or .zip with your project (import only) — becomes the first commit\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--timeout <ms>\", \"Timeout in milliseconds\", \"600000\")\n .option(\"--verbose\", \"Show progress on stderr\")\n .option(\"--api-url <url>\", \"API base URL (overrides config / ANIMA_API_URL)\")\n .option(\"--log-file <path>\", \"Append a JSON debug log of each step to this file\")\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const type = opts.type as CreateType;\n validateCreateOptions(type, opts);\n\n const auth = resolveAuth();\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 (playground-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>(\"playground-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 playground...\"\n : type === \"import\"\n ? \"Importing your project...\"\n : `Creating ${type.toUpperCase()} playground...`\n );\n\n const result = await withMcp(mcpConfig, (client) =>\n client.callTool<CreateResult>(\"playground-create\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.sessionId) {\n const message = result.reason || result.error || \"Generation failed\";\n // Own-code failures carry recovery guidance (e.g. the upload_not_found\n // duplicate-playground warning) — losing it at the CLI boundary would\n // strip exactly what the caller needs to retry correctly.\n throw apiError(result.nextSteps ? `${message}\\n${result.nextSteps}` : message, result);\n }\n\n const playgroundUrl = result.playgroundUrl || `${PLAYGROUND_BASE}/${result.sessionId}`;\n\n progress.succeed(\"Playground created!\");\n\n if (mode === \"pretty\") {\n printSessionResult({ sessionId: result.sessionId, playgroundUrl });\n if (result.gitRemoteUrl) {\n console.log(` ${chalk.cyan(`git clone ${result.gitRemoteUrl}`)}`);\n console.log();\n console.log(\" Commit and push to update the live playground.\");\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 playground.\");\n console.log();\n } else if (type === \"empty\") {\n console.log(\n ` Next: anima get-git-token ${result.sessionId} — then git clone, add your code, and git push.`\n );\n console.log();\n }\n if (type === \"import\" && result.fileCount !== undefined) {\n console.log(` ${result.fileCount} files committed (framework: ${result.framework ?? \"detected server-side\"}).`);\n if (result.skippedFiles?.length) {\n console.log(` Skipped (blocked/hidden): ${result.skippedFiles.join(\", \")}`);\n }\n if (result.notes) {\n console.log(` Note: ${result.notes}`);\n }\n console.log();\n }\n } else {\n outputResult(mode, {\n success: true,\n sessionId: result.sessionId,\n playgroundUrl,\n ...(result.gitRemoteUrl\n ? { gitRemoteUrl: result.gitRemoteUrl, access: result.access, expiresAt: result.expiresAt }\n : {}),\n ...(result.framework ? { framework: result.framework } : {}),\n ...(result.fileCount !== undefined ? { fileCount: result.fileCount } : {}),\n ...(result.skippedFiles?.length ? { skippedFiles: result.skippedFiles } : {}),\n ...(result.notes ? { notes: result.notes } : {}),\n ...(result.nextSteps ? { nextSteps: result.nextSteps } : {}),\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\nfunction validateCreateOptions(type: CreateType, opts: Record<string, string>): void {\n if (![\"p2c\", \"l2c\", \"f2c\", \"empty\", \"import\"].includes(type)) {\n throw validationError(`Invalid type \"${type}\". Must be p2c, l2c, f2c, empty, or import.`);\n }\n if (type === \"p2c\" && !opts.prompt) {\n throw validationError(\"--prompt is required for p2c type\");\n }\n if (type === \"l2c\" && !opts.url) {\n throw validationError(\"--url is required for l2c type\");\n }\n if (type === \"f2c\" && !opts.fileKey) {\n throw validationError(\"--file-key is required for f2c type\");\n }\n if (type === \"empty\" && !opts.framework) {\n throw validationError(\n \"--framework is required for type empty — html for plain HTML/CSS/JS, react for React (declare react if you will push React code)\"\n );\n }\n if (type === \"import\" && !opts.from) {\n throw validationError(\"--from <folder|zip> is required for type import — the path to the project to import\");\n }\n if (type !== \"import\" && opts.from) {\n throw validationError(\"--from is only valid with -t import\");\n }\n}\n\nfunction resolveFigmaToken(opts: Record<string, string>, stored?: string): string {\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || stored;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required for f2c. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n return figmaToken;\n}\n\nfunction buildCreateArgs(type: CreateType, opts: Record<string, string>): Record<string, unknown> {\n // empty: framework is required (validated above) — the caller declares what\n // they'll push. import: framework only when explicit — the server detects\n // it from package.json otherwise. The files/zipUploadId for import are\n // attached later by the action (they may need the upload leg first).\n if (type === \"empty\" || type === \"import\") {\n return {\n type,\n ...(opts.framework ? { framework: opts.framework } : {}),\n ...(opts.name ? { name: opts.name } : {}),\n };\n }\n\n // Generation types: html is the default — aligned with the MCP\n // playground-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 args: Record<string, unknown> = {\n type,\n framework,\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n switch (type) {\n case \"p2c\":\n args.prompt = opts.prompt;\n if (opts.guidelines) args.guidelines = opts.guidelines;\n break;\n case \"l2c\":\n args.url = opts.url;\n break;\n case \"f2c\": {\n const { fileKey, nodeId: parsedNodeId } = parseFigmaUrl(opts.fileKey);\n let nodesId: string[] = [];\n if (opts.nodes) {\n nodesId = opts.nodes.split(\",\").map((n) => normalizeNodeId(n.trim()));\n } else if (parsedNodeId) {\n nodesId = [parsedNodeId];\n }\n args.fileKey = fileKey;\n args.nodesId = nodesId;\n break;\n }\n }\n\n return args;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".config\", \"anima\");\nconst CREDENTIALS_FILE = path.join(CONFIG_DIR, \"credentials.json\");\n\ntype Credentials = {\n token: string;\n teamId?: string;\n figmaToken?: string;\n // Set by the device login: a scoped, revocable AGENT token — never to be\n // confused with a personal API token (which carries the user's full\n // authority and is not governed by workspace scopes).\n tokenType?: \"agent\" | \"personal\";\n agentId?: string;\n expiresAt?: string; // ISO — agent tokens expire (~7 days); re-run the login\n};\n\nexport function readCredentials(): Credentials | null {\n try {\n if (!fs.existsSync(CREDENTIALS_FILE)) return null;\n const content = fs.readFileSync(CREDENTIALS_FILE, \"utf-8\");\n const parsed = JSON.parse(content);\n if (!parsed.token) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nexport function writeCredentials(credentials: Partial<Credentials>): void {\n // Merge with existing credentials so we can update fields independently\n const existing = readCredentials() ?? {};\n const merged = { ...existing, ...credentials };\n\n // Remove undefined values\n for (const key of Object.keys(merged) as (keyof Credentials)[]) {\n if (merged[key] === undefined) delete merged[key];\n }\n\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(\n CREDENTIALS_FILE,\n JSON.stringify(merged, null, 2) + \"\\n\",\n { mode: 0o600 }\n );\n}\n\nexport function deleteCredentials(): boolean {\n try {\n if (fs.existsSync(CREDENTIALS_FILE)) {\n fs.unlinkSync(CREDENTIALS_FILE);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Full logout: remove every stored token (all live in credentials.json) and\n * the config directory itself when nothing else is left in it. Returns whether\n * any credentials were present.\n */\nexport function clearStorage(): boolean {\n const had = deleteCredentials();\n try {\n if (fs.existsSync(CONFIG_DIR) && fs.readdirSync(CONFIG_DIR).length === 0) {\n fs.rmdirSync(CONFIG_DIR);\n }\n } catch {\n /* leaving an empty dir behind is harmless */\n }\n return had;\n}\n\nexport function getCredentialsPath(): string {\n return CREDENTIALS_FILE;\n}\n\n/**\n * Extract the defaultTeamId from a JWT token payload (base64-decoded, no verification).\n * Returns undefined if extraction fails.\n */\nexport function extractTeamIdFromJWT(token: string): string | undefined {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) return undefined;\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf-8\")\n );\n return payload.defaultTeamId ?? undefined;\n } catch {\n return undefined;\n }\n}\n","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 { readCredentials } from \"./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\" | \"personal\";\n};\n\nexport function resolveAuth(): ResolvedAuth {\n const creds = readCredentials();\n\n // 1. Environment variable (primary — what AI tools use)\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 || creds?.figmaToken,\n source: \"env\",\n };\n }\n\n // 2. Stored credentials file\n if (creds) {\n // Agent tokens expire (~7 days); renewal is a fresh device login, which\n // reconnects to the same agent when the same name is approved.\n if (creds.tokenType === \"agent\" && creds.expiresAt && new Date(creds.expiresAt) <= new Date()) {\n throw authError(\"Your agent token has expired. Run: anima login\");\n }\n return {\n token: creds.token,\n teamId: creds.teamId,\n figmaToken: process.env.FIGMA_TOKEN || creds.figmaToken,\n source: \"file\",\n tokenType: creds.tokenType,\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 Anima 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 Anima MCP endpoint: ${message}`,\n 1\n );\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 { createRequire } from \"node:module\";\n\n// Single source for the CLI version: package.json. `../package.json` resolves\n// from src/ in dev and from dist/index.js in the published bundle — this file\n// must stay directly under src/ for that to hold.\nexport const { version } = createRequire(import.meta.url)(\"../package.json\") as { version: string };\n","export type OutputMode = \"json\" | \"pretty\";\n\nexport function detectOutputMode(flags: {\n json?: boolean;\n}): OutputMode {\n if (flags.json !== undefined) {\n return flags.json ? \"json\" : \"pretty\";\n }\n // Auto-detect: JSON when piped, pretty in TTY\n return process.stdout.isTTY ? \"pretty\" : \"json\";\n}\n\nexport function outputResult(mode: OutputMode, data: unknown): void {\n if (mode === \"json\") {\n process.stdout.write(JSON.stringify(data) + \"\\n\");\n }\n // Pretty mode output is handled inline by commands using chalk/ora\n}\n\nexport function outputError(\n mode: OutputMode,\n error: { code: string; message: string }\n): void {\n if (mode === \"json\") {\n process.stdout.write(\n JSON.stringify({ success: false, error }) + \"\\n\"\n );\n }\n // Pretty mode errors are handled inline by commands\n}\n","import ora, { type Ora } from \"ora\";\nimport type { OutputMode } from \"./formatter.js\";\n\nexport class ProgressReporter {\n #spinner: Ora | null = null;\n #mode: OutputMode;\n #startTime: number = 0;\n #verbose: boolean;\n\n constructor(mode: OutputMode, verbose: boolean = false) {\n this.#mode = mode;\n this.#verbose = verbose;\n }\n\n start(message: string): void {\n this.#startTime = Date.now();\n if (this.#mode === \"pretty\") {\n // A previous phase's spinner must be stopped first: an orphaned ora\n // interval keeps the event loop (and its repaints) alive forever.\n this.#spinner?.stop();\n this.#spinner = ora(message).start();\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"started\", message }) + \"\\n\");\n }\n }\n\n update(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.text = `${message} ${elapsed}`;\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"progress\", message }) + \"\\n\");\n }\n }\n\n succeed(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n const elapsed = this.#elapsed();\n this.#spinner.succeed(`${message} ${elapsed}`);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"done\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n fail(message: string): void {\n if (this.#mode === \"pretty\" && this.#spinner) {\n this.#spinner.fail(message);\n } else if (this.#verbose) {\n process.stderr.write(JSON.stringify({ status: \"error\", message }) + \"\\n\");\n }\n this.#spinner = null;\n }\n\n #elapsed(): string {\n const ms = Date.now() - this.#startTime;\n const seconds = Math.floor(ms / 1000);\n if (seconds < 60) return `(${seconds}s)`;\n const minutes = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `(${minutes}m ${secs}s)`;\n }\n}\n","import chalk from \"chalk\";\n\nexport function printSuccess(message: string): void {\n console.log(chalk.green(\"✓\") + \" \" + message);\n}\n\nexport function printError(message: string): void {\n console.error(chalk.red(\"✗\") + \" \" + message);\n}\n\nexport function printInfo(message: string): void {\n console.log(chalk.blue(\"ℹ\") + \" \" + message);\n}\n\nexport function printWarning(message: string): void {\n console.log(chalk.yellow(\"⚠\") + \" \" + message);\n}\n\nexport function printKeyValue(key: string, value: string): void {\n console.log(` ${chalk.gray(key + \":\")} ${value}`);\n}\n\nexport function printSessionResult(result: {\n sessionId: string;\n playgroundUrl?: string;\n tokenUsage?: number;\n}): void {\n console.log();\n printSuccess(\"Playground created successfully!\");\n printKeyValue(\"Session ID\", result.sessionId);\n if (result.playgroundUrl) {\n printKeyValue(\"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: {\n url?: string;\n packageUrl?: string;\n packageName?: string;\n packageVersion?: string;\n}): void {\n console.log();\n printSuccess(\"Published successfully!\");\n if (result.url) {\n printKeyValue(\"Live URL\", chalk.cyan.underline(result.url));\n }\n if (result.packageName) {\n printKeyValue(\"Package\", result.packageName);\n printKeyValue(\"Version\", result.packageVersion ?? \"\");\n if (result.packageUrl) {\n printKeyValue(\"URL\", chalk.cyan.underline(result.packageUrl));\n }\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 playground-create\n * - zip: anything with binaries or over the inline caps, or a .zip given\n * directly → playground-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 playground-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","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://public-api.animaapp.com\";\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 { 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 { validationError, CliError } from \"../api/errors.js\";\n\nexport const publishCommand = new Command(\"publish\")\n .description(\"Deploy playground to live URL or npm package (1-3 min)\")\n .argument(\"<sessionId>\", \"Session ID from create command\")\n .option(\"--mode <mode>\", \"webapp | designSystem\", \"webapp\")\n .option(\"--package-name <name>\", \"NPM package name (designSystem mode)\")\n .option(\"--package-version <version>\", \"NPM package version (designSystem mode)\")\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 (![\"webapp\", \"designSystem\"].includes(opts.mode)) {\n throw validationError(\n `Invalid mode \"${opts.mode}\". Must be webapp or designSystem.`\n );\n }\n\n if (opts.mode === \"designSystem\" && !opts.packageName) {\n throw validationError(\"--package-name is required for designSystem mode\");\n }\n\n const auth = resolveAuth();\n\n const args: Record<string, unknown> = {\n sessionId,\n mode: opts.mode,\n };\n if (opts.packageName) args.packageName = opts.packageName;\n if (opts.packageVersion) args.packageVersion = opts.packageVersion;\n\n progress.start(`Publishing as ${opts.mode}...`);\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>>(\"playground-publish\", args, {\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({\n url: result.liveUrl as string | undefined,\n packageUrl: result.packageUrl as string | undefined,\n packageName: result.packageName as string | undefined,\n packageVersion: result.packageVersion as string | undefined,\n });\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n ...(result.liveUrl ? { liveUrl: result.liveUrl, subdomain: result.subdomain } : {}),\n ...(result.packageName\n ? {\n packageName: result.packageName,\n packageVersion: result.packageVersion,\n packageUrl: result.packageUrl,\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 { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { printFilesWritten } from \"../output/pretty.js\";\nimport { parseFigmaUrl, normalizeNodeId } from \"../utils/figma.js\";\nimport { writeFilesToDisk } from \"../utils/files.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { validationError, apiError, CliError } from \"../api/errors.js\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\ntype CodegenResult = {\n success: boolean;\n sessionId?: string;\n files?: AnimaFiles;\n tokenUsage?: number;\n error?: string;\n reason?: string;\n};\n\nexport const codegenCommand = new Command(\"codegen\")\n .description(\"Convert Figma design to code files (no playground)\")\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 = resolveAuth();\n\n // Resolve Figma token: flag > env var > stored credentials > error.\n // Sent via the X-Figma-Token header; the tool reads it from the header.\n const figmaToken = opts.figmaToken || process.env.FIGMA_TOKEN || auth.figmaToken;\n if (!figmaToken) {\n throw validationError(\n \"Figma token required. Use --figma-token, set FIGMA_TOKEN env var, or run: anima auth --figma-token <token>\\n\" +\n \"Get one at: https://www.figma.com > Settings > Personal access tokens\"\n );\n }\n\n // Default language to typescript when framework is react.\n const language = opts.language ?? (opts.framework === \"react\" ? \"typescript\" : undefined);\n\n const args: Record<string, unknown> = {\n fileKey,\n nodesId,\n framework: opts.framework,\n styling: opts.styling,\n };\n if (language) args.language = language;\n if (opts.uiLibrary) args.uiLibrary = opts.uiLibrary;\n\n progress.start(\"Generating code from Figma...\");\n\n const result = await withMcp(\n { apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId, figmaToken },\n (client) =>\n client.callTool<CodegenResult>(\"codegen-figma_to_code\", args, {\n timeoutMs: parseInt(opts.timeout, 10),\n onProgress: (p) => progress.update(p.message ?? `Generating (${Math.round(p.progress)}%)...`),\n })\n );\n\n if (!result.success || !result.files) {\n throw apiError(result.reason || result.error || \"Code generation failed\", result);\n }\n\n const count = writeFilesToDisk(result.files, opts.output);\n\n progress.succeed(`Generated ${count} files`);\n\n if (mode === \"pretty\") {\n printFilesWritten(opts.output, count);\n } else {\n outputResult(mode, {\n success: true,\n output: opts.output,\n fileCount: count,\n sessionId: result.sessionId,\n tokenUsage: result.tokenUsage,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AnimaFiles } from \"../api/types.js\";\n\n/**\n * Write generated files to disk.\n * Handles both code (text) and binary (base64-encoded) files.\n */\nexport function writeFilesToDisk(\n files: AnimaFiles,\n outputDir: string\n): number {\n // Create output directory\n fs.mkdirSync(outputDir, { recursive: true });\n\n let count = 0;\n\n const resolvedOutput = path.resolve(outputDir);\n\n for (const [filePath, fileContent] of Object.entries(files)) {\n const fullPath = path.resolve(outputDir, filePath);\n\n if (!fullPath.startsWith(resolvedOutput + path.sep)) {\n throw new Error(`Path traversal detected: ${filePath}`);\n }\n\n // Create parent directories\n const dirPath = path.dirname(fullPath);\n fs.mkdirSync(dirPath, { recursive: true });\n\n if (fileContent.isBinary) {\n const buffer = Buffer.from(fileContent.content, \"base64\");\n fs.writeFileSync(fullPath, buffer);\n } else {\n fs.writeFileSync(fullPath, fileContent.content, \"utf-8\");\n }\n\n count++;\n }\n\n return count;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { withMcp } from \"../api/mcp.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { ProgressReporter } from \"../output/progress.js\";\nimport { initLogger, logEvent } from \"../output/log.js\";\nimport { parsePlaygroundUrl } from \"../utils/playgroundUrl.js\";\nimport { parseGitTokenResponse } from \"../utils/gitToken.js\";\nimport { resolveApiUrl } from \"../config/store.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * Mirror of the `project-get_git_token` MCP tool — git is the only content\n * plane for playground 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 playground\n * git remote set-url origin <url> # after expiry: point the clone at a fresh URL\n *\n * The token expires within an hour and cannot be renewed — re-run this command\n * for a fresh URL.\n */\nexport const getGitTokenCommand = new Command(\"get-git-token\")\n .description(\"Mint a short-lived git remote URL for a playground (clone/push with git)\")\n .argument(\"<playgroundUrl>\", \"Playground 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 (playgroundUrl: string, opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n const progress = new ProgressReporter(mode, opts.verbose);\n\n try {\n const sessionId = parsePlaygroundUrl(playgroundUrl);\n const auth = resolveAuth();\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>(\"project-get_git_token\", { sessionId })\n );\n\n const grant = parseGitTokenResponse(response);\n logEvent(\"git_token_granted\", { sessionId, access: grant.access, expiresAt: grant.expiresAt });\n\n progress.succeed(`Git access granted (${grant.access === \"rw\" ? \"read-write\" : \"read-only\"})`);\n\n if (mode === \"pretty\") {\n console.log();\n console.log(` ${chalk.cyan(`git clone ${grant.gitRemoteUrl}`)}`);\n console.log();\n if (grant.access === \"rw\") {\n console.log(\" Commit and push to update the live playground.\");\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 playground.\");\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n sessionId,\n gitRemoteUrl: grant.gitRemoteUrl,\n access: grant.access,\n expiresAt: grant.expiresAt,\n });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n console.error(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","/**\n * Parse a playground URL to extract the session ID.\n * Supported formats:\n * - https://dev.animaapp.com/chat/SESSION_ID\n * - Just a session ID string\n */\nexport function parsePlaygroundUrl(input: string): string {\n if (!input.includes(\"/\")) {\n return input;\n }\n\n try {\n const url = new URL(input);\n const parts = url.pathname.split(\"/\").filter(Boolean);\n // Expected: /chat/SESSION_ID\n const chatIndex = parts.indexOf(\"chat\");\n if (chatIndex !== -1 && chatIndex + 1 < parts.length) {\n return parts[chatIndex + 1];\n }\n // Fallback: last path segment\n return parts[parts.length - 1];\n } catch {\n // Not a URL, treat as session ID\n return input;\n }\n}\n","import { apiError } from \"../api/errors.js\";\n\n/**\n * Parsed outcome of the `project-get_git_token` MCP tool.\n *\n * The tool returns JSON: `{ success, gitRemoteUrl, access, expiresAt }` on a\n * grant, or `{ success: false, error, reason }` on a denial. The MCP client\n * (api/mcp.ts) already JSON-parses tool text, so this receives the parsed\n * object — a string only arrives if that parse failed. The clone URL embeds a\n * short-lived access token scoped to the one playground.\n */\nexport type GitTokenGrant = {\n gitRemoteUrl: string;\n access: \"ro\" | \"rw\";\n expiresAt?: string;\n};\n\nfunction preview(payload: unknown): string {\n const text = typeof payload === \"string\" ? payload : JSON.stringify(payload);\n return (text ?? String(payload)).slice(0, 200);\n}\n\nexport function parseGitTokenResponse(payload: unknown): GitTokenGrant {\n let value = payload;\n if (typeof value === \"string\") {\n try {\n value = JSON.parse(value);\n } catch {\n throw apiError(`Unexpected response from project-get_git_token: ${preview(payload)}`);\n }\n }\n\n if (value === null || typeof value !== \"object\") {\n throw apiError(`Unexpected response from project-get_git_token: ${preview(payload)}`);\n }\n\n const body = value as {\n success?: boolean;\n error?: string;\n reason?: string;\n gitRemoteUrl?: string;\n access?: string;\n expiresAt?: string;\n };\n\n if (body.success === false) {\n throw apiError(`Git access ${body.error ?? \"denied\"}: ${(body.reason ?? \"\").trim()}`);\n }\n\n if (!body.gitRemoteUrl) {\n throw apiError(`Unexpected response from project-get_git_token: ${preview(payload)}`);\n }\n\n return {\n gitRemoteUrl: body.gitRemoteUrl,\n access: body.access === \"rw\" ? \"rw\" : \"ro\",\n expiresAt: body.expiresAt,\n };\n}\n","import { Command } from \"commander\";\nimport { resolveAuth } from \"../auth/token.js\";\nimport { readCredentials } from \"../auth/store.js\";\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 from EXISTING credentials — no network, no new\n * device flow. This is the \"I'm already logged in, give me my config\" command\n * the /connect guide's Step 2 points at; `login --print-mcp-config` remains\n * the one-shot variant (fresh login, then print).\n */\nexport const mcpConfigCommand = new Command(\"mcp-config\")\n .description(\"Print an MCP server config from your stored credentials (run `login` first)\")\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 // Resolution + expiry checks live in resolveAuth: env token → stored\n // credentials (expired agent token → clear \"run anima login\" error).\n const auth = resolveAuth();\n const creds = readCredentials();\n const expiresAt = auth.source === \"env\" ? undefined : creds?.expiresAt;\n\n const mcpConfig = buildMcpConfig(resolveApiUrl(opts.apiUrl), auth.token);\n\n if (mode === \"pretty\") {\n printInfo(\"MCP server config (add to your MCP client; the token is a secret):\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n console.log();\n if (expiresAt) {\n printInfo(`Token expires ${expiresAt} — run \\`anima login\\` then \\`anima mcp-config\\` to refresh.`);\n }\n } else {\n outputResult(mode, {\n success: true,\n mcpConfig,\n ...(expiresAt ? { expiresAt } : {}),\n ...(creds?.agentId && auth.source !== \"env\" ? { agentId: creds.agentId } : {}),\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","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { loginWithDeviceFlow } from \"../auth/device.js\";\nimport { loginWithInvite, parseInvite } from \"../auth/invite.js\";\nimport { getCredentialsPath } from \"../auth/store.js\";\nimport { initLogger } from \"../output/log.js\";\nimport { resolveApiUrl, setConfig, readConfig } from \"../config/store.js\";\nimport { detectOutputMode, outputResult, outputError } from \"../output/formatter.js\";\nimport { printSuccess, printError, printKeyValue, printInfo } from \"../output/pretty.js\";\nimport { CliError } from \"../api/errors.js\";\n\n/**\n * `anima login` — connect this machine as a governed agent.\n *\n * Two doors, one credential store:\n * - Default: the OAuth device flow. The command prints a short code and a\n * verification URL; a human approves on any device — choosing which\n * workspaces and capabilities this agent gets — and the CLI picks up its\n * scoped token automatically.\n * - `--invite <url-or-code>`: redeem a pre-approved invite (the human already\n * consented in-app when minting it) — a single exchange, no human step and\n * no browser.\n * Either way the token expires after ~7 days; logging in again with the same\n * agent name reconnects to the same agent identity.\n */\nexport const loginCommand = new Command(\"login\")\n .description(\"Log in via the device flow, or redeem a pre-approved invite with --invite\")\n .option(\"--invite <url-or-code>\", \"Redeem an invite link (…/invite/<code>.md) or bare code — no approval step\")\n .option(\"--client-name <name>\", \"How this CLI appears on the consent screen\", \"Anima 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 (includes the token) to paste into an MCP-capable agent\"\n )\n .action(async (opts) => {\n const mode = detectOutputMode(opts);\n initLogger(opts.logFile);\n\n if (opts.invite) {\n // The invite URL was minted on the API the human used, so its origin is\n // the right base unless the caller explicitly overrides it.\n const inviteOrigin = parseInvite(opts.invite).origin;\n const apiUrl = opts.apiUrl ? resolveApiUrl(opts.apiUrl) : (inviteOrigin ?? resolveApiUrl());\n\n try {\n const result = await loginWithInvite({ apiUrl, invite: opts.invite });\n // Persist the origin the invite was redeemed on: the token is only\n // valid THERE, so later commands (get-git-token, mcp-config, …) must\n // default to it instead of the built-in API URL.\n if (inviteOrigin && readConfig().apiUrl !== apiUrl) {\n setConfig(\"api-url\", apiUrl);\n }\n const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl, result.token) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n if (result.agentId) printKeyValue(\"Agent\", result.agentId);\n if (result.teamId) printKeyValue(\"Team ID\", result.teamId);\n if (result.expiresAt) 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 (token expires ~7 days — a fresh invite renews it):\");\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, result.token) : undefined;\n\n if (mode === \"pretty\") {\n printSuccess(\"Connected!\");\n printKeyValue(\"Credentials\", getCredentialsPath());\n if (result.agentId) printKeyValue(\"Agent\", result.agentId);\n if (result.teamId) printKeyValue(\"Team ID\", result.teamId);\n if (result.expiresAt) 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 (token expires ~7 days — re-run `anima login` to refresh):\");\n console.log();\n console.log(JSON.stringify(mcpConfig, null, 2));\n }\n } else {\n outputResult(mode, {\n success: true,\n action: \"logged_in\",\n tokenType: \"agent\",\n agentId: result.agentId,\n teamId: result.teamId,\n expiresAt: result.expiresAt,\n ...(mcpConfig ? { mcpConfig } : {}),\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n\n/**\n * A remote MCP server entry an MCP-capable agent can add to talk to Anima\n * directly (no CLI in the loop). Exact keys vary by client; this is the common\n * `mcpServers` shape with a bearer header. The URL honors --api-url/config so a\n * local login yields a local config.\n */\nexport function buildMcpConfig(apiUrl: string, token: string) {\n return {\n mcpServers: {\n anima: {\n type: \"http\",\n url: `${apiUrl.replace(/\\/$/, \"\")}/v1/mcp`,\n headers: { Authorization: `Bearer ${token}` },\n },\n },\n };\n}\n","import { writeCredentials } from \"./store.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. It expires after ~7 days; renewal is simply running\n * the flow again (re-approval reconnects to the same agent when the same\n * agent name is kept).\n */\n\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst DEFAULT_CLIENT_NAME = \"Anima CLI\";\n\nexport type DeviceVerificationInfo = {\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresInSeconds: number;\n};\n\nexport type DeviceLoginResult = {\n token: string;\n teamId?: string;\n agentId?: string;\n expiresAt?: string;\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\n/** Decode a JWT payload without verification (display/bookkeeping only). */\nfunction 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\nexport async function loginWithDeviceFlow(options: DeviceLoginOptions): Promise<DeviceLoginResult> {\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 token = body.access_token;\n const claims = decodeJwtPayload(token);\n const result: DeviceLoginResult = {\n token,\n teamId: typeof claims?.team_id === \"string\" ? claims.team_id : undefined,\n agentId: typeof claims?.agent_id === \"string\" ? claims.agent_id : undefined,\n expiresAt:\n typeof claims?.exp === \"number\" ? new Date(claims.exp * 1000).toISOString() : undefined,\n };\n\n writeCredentials({\n token: result.token,\n teamId: result.teamId,\n tokenType: \"agent\",\n agentId: result.agentId,\n expiresAt: result.expiresAt,\n });\n\n return result;\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 { writeCredentials } from \"./store.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://public-api.animaapp.com/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\nexport type InviteLoginResult = {\n token: string;\n teamId?: string;\n agentId?: string;\n expiresAt?: string;\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\n/** Decode a JWT payload without verification (display/bookkeeping only). */\nfunction 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\nexport async function loginWithInvite(options: InviteLoginOptions): Promise<InviteLoginResult> {\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 token = body.access_token;\n const claims = decodeJwtPayload(token);\n const result: InviteLoginResult = {\n token,\n teamId: typeof claims?.team_id === \"string\" ? claims.team_id : undefined,\n agentId: typeof claims?.agent_id === \"string\" ? claims.agent_id : undefined,\n expiresAt: typeof claims?.exp === \"number\" ? new Date(claims.exp * 1000).toISOString() : undefined,\n };\n\n // Same credential shape as the device login — the whole CLI surface\n // (logout, mcp-config, get-git-token, …) works identically from here.\n writeCredentials({\n token: result.token,\n teamId: result.teamId,\n tokenType: \"agent\",\n agentId: result.agentId,\n expiresAt: result.expiresAt,\n });\n\n return result;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { writeCredentials, clearStorage, readCredentials, getCredentialsPath, extractTeamIdFromJWT } from \"../auth/store.js\";\nimport { resolveAuth } from \"../auth/token.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://public-api.animaapp.com\";\n\nexport const authCommand = new Command(\"auth\")\n .description(\"Manage authentication\")\n .option(\"--token <token>\", \"Store Anima 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: Record<string, string> = {};\n\n if (opts.token) {\n toSave.token = opts.token;\n toSave.teamId = opts.teamId ?? extractTeamIdFromJWT(opts.token) ?? \"\";\n }\n if (opts.figmaToken) {\n toSave.figmaToken = opts.figmaToken;\n }\n\n writeCredentials(toSave);\n\n if (mode === \"pretty\") {\n printSuccess(\"Credentials saved to \" + getCredentialsPath());\n if (opts.token) {\n printKeyValue(\"Anima 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 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 });\n }\n return;\n }\n\n if (opts.status) {\n try {\n const auth = resolveAuth();\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(\"Anima token\", auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4));\n printKeyValue(\"Token type\", auth.tokenType === \"agent\" ? \"agent (scoped, revocable)\" : \"personal/API\");\n if (creds?.tokenType === \"agent\" && creds.expiresAt) printKeyValue(\"Expires\", creds.expiresAt);\n if (auth.teamId) printKeyValue(\"Team ID\", auth.teamId);\n printKeyValue(\"Figma token\", hasFigma ? \"configured\" : \"not set (needed for codegen/f2c)\");\n } else {\n outputResult(mode, {\n success: true,\n source: auth.source,\n tokenType: auth.tokenType ?? \"personal\",\n tokenPreview: auth.token.slice(0, 12) + \"...\" + auth.token.slice(-4),\n teamId: auth.teamId,\n expiresAt: creds?.tokenType === \"agent\" ? creds.expiresAt : undefined,\n figmaToken: hasFigma,\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n } else {\n throw err;\n }\n }\n return;\n }\n\n // No flag: show help\n if (mode === \"pretty\") {\n console.log();\n printInfo(\"Auth commands:\");\n console.log(` ${chalk.cyan(\"anima login\")} Log in (device flow — approve on any browser)`);\n console.log(` ${chalk.cyan(\"anima logout\")} Clear all credentials`);\n console.log(` ${chalk.cyan(\"anima auth --status\")} Check auth status`);\n console.log(` ${chalk.cyan(\"anima auth --figma-token <T>\")} Save Figma token (needed for codegen/f2c)`);\n console.log();\n console.log(` Figma token: ${chalk.cyan.underline(\"https://www.figma.com\")} > Settings > Personal access tokens`);\n console.log();\n } else {\n outputResult(mode, {\n success: true,\n message: \"Run `anima login`, or use --status / --logout / --figma-token\",\n });\n }\n } catch (err) {\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport { clearStorage, getCredentialsPath } from \"../auth/store.js\";\nimport { deleteConfig } 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. Note: this only forgets the token locally; to actually disable an\n * agent, revoke it from your team settings.\n */\nexport const logoutCommand = new Command(\"logout\")\n .description(\"Clear all stored credentials (Anima + Figma tokens) from this machine\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const mode = detectOutputMode(opts);\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 } else {\n printInfo(\"No stored credentials found\");\n }\n } else {\n outputResult(mode, { success: true, action: \"logged_out\", hadCredentials });\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 `playground-unpublish` MCP tool — the inverse of `publish`. */\nexport const unpublishCommand = new Command(\"unpublish\")\n .description(\"Take a published playground offline (clears its live URL; code and playground stay intact)\")\n .argument(\"<sessionId>\", \"Session ID of the published playground\")\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 = resolveAuth();\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>(\"playground-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 || `Playground ${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 `playground-metadata-update` MCP tool — metadata only (name,\n * visibility); it never touches code or content (that is the git flow).\n */\nexport const updateCommand = new Command(\"update\")\n .description(\"Update a playground's metadata: display name and/or visibility (never touches code)\")\n .argument(\"<sessionId>\", \"Session ID of the playground\")\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 = resolveAuth();\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>(\"playground-metadata-update\", {\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 || `Playground ${sessionId} updated.`);\n } else {\n outputResult(mode, { success: true, sessionId, ...(result.message ? { message: result.message } : {}) });\n }\n } catch (err) {\n progress.fail(\"Failed\");\n if (err instanceof CliError) {\n if (mode === \"pretty\") {\n printError(err.message);\n } else {\n outputError(mode, { code: err.code, message: err.message });\n }\n process.exit(err.exitCode);\n }\n throw err;\n }\n });\n","import { Command } from \"commander\";\nimport {\n readConfig,\n setConfig,\n unsetConfig,\n getConfigPath,\n isConfigKey,\n configKeys,\n CONFIG_KEYS,\n resolveApiUrl,\n DEFAULT_API_URL,\n type ConfigKey,\n} from \"../config/store.js\";\nimport { detectOutputMode, outputResult } from \"../output/formatter.js\";\nimport { printSuccess, printInfo, printKeyValue } from \"../output/pretty.js\";\nimport { validationError } from \"../api/errors.js\";\n\n/**\n * `anima config` — store non-secret CLI preferences in\n * ~/.config/anima/config.json so you don't have to pass flags like `--api-url`\n * every time. Resolution precedence for the API URL: flag → ANIMA_API_URL env →\n * stored config → default.\n *\n * anima config set api-url http://localhost:3789\n * anima config get api-url\n * anima config list\n * anima config unset api-url\n */\nexport const configCommand = new Command(\"config\").description(\n `Store CLI preferences (keys: ${configKeys().join(\", \")})`\n);\n\nconfigCommand\n .command(\"set <key> <value>\")\n .description(\"Set a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, value: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n if (key === \"api-url\") assertUrl(value);\n setConfig(key, value);\n\n if (mode === \"pretty\") printSuccess(`Set ${key} = ${value}`);\n else outputResult(mode, { success: true, action: \"config_set\", key, value });\n });\n\nconfigCommand\n .command(\"get <key>\")\n .description(\"Print a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const value = readConfig()[CONFIG_KEYS[key]];\n\n if (mode === \"pretty\") {\n if (value) console.log(value);\n else printInfo(`${key} is not set`);\n } else {\n outputResult(mode, { success: true, key, value: value ?? null });\n }\n });\n\nconfigCommand\n .command(\"list\")\n .alias(\"ls\")\n .description(\"Show all config values and where the API URL resolves from\")\n .option(\"--json\", \"Output as JSON\")\n .action((opts) => {\n const mode = detectOutputMode(opts);\n const config = readConfig();\n const resolvedApiUrl = resolveApiUrl();\n\n if (mode === \"pretty\") {\n printInfo(\"Config: \" + getConfigPath());\n printKeyValue(\"api-url\", config.apiUrl ?? `(default) ${DEFAULT_API_URL}`);\n if (process.env.ANIMA_API_URL) {\n printInfo(`ANIMA_API_URL env is set — it overrides config (effective: ${resolvedApiUrl})`);\n }\n } else {\n outputResult(mode, {\n success: true,\n path: getConfigPath(),\n config,\n resolved: { apiUrl: resolvedApiUrl },\n });\n }\n });\n\nconfigCommand\n .command(\"unset <key>\")\n .description(\"Remove a config value\")\n .option(\"--json\", \"Output as JSON\")\n .action((key: string, opts) => {\n const mode = detectOutputMode(opts);\n assertKey(key);\n const removed = unsetConfig(key);\n\n if (mode === \"pretty\") {\n if (removed) printSuccess(`Unset ${key}`);\n else printInfo(`${key} was not set`);\n } else {\n outputResult(mode, { success: true, action: \"config_unset\", key, removed });\n }\n });\n\nfunction assertKey(key: string): asserts key is ConfigKey {\n if (!isConfigKey(key)) {\n throw validationError(`Unknown config key \"${key}\". Valid keys: ${configKeys().join(\", \")}`);\n }\n}\n\nfunction assertUrl(value: string): void {\n try {\n new URL(value);\n } catch {\n throw validationError(`\"${value}\" is not a valid URL`);\n }\n}\n"],"mappings":"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","names":["Command","chalk","fs","path","path","fs","path","os","CONFIG_DIR","chalk","Command","Command","Command","fs","path","Command","Command","chalk","Command","chalk","Command","Command","chalk","decodeJwtPayload","Command","apiUrl","chalk","Command","Command","chalk","DEFAULT_API_URL","Command","chalk","Command","Command","Command","Command","Command","Command","Command","Command","Command"]}
|