@animaapp/cli 0.3.10 → 0.3.11

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 CHANGED
@@ -112,10 +112,12 @@ npx @animaapp/cli login
112
112
  npx @animaapp/cli login --client-name "My CI Agent" # label on the consent screen
113
113
  npx @animaapp/cli login --no-open # don't auto-open the browser
114
114
  npx @animaapp/cli login --print-mcp-config # also emit an MCP server config
115
+ npx @animaapp/cli login --invite <url-or-code> # redeem a pre-approved invite — no approval step
115
116
  ```
116
117
 
117
118
  | Option | Description | Default |
118
119
  |--------|-------------|---------|
120
+ | `--invite <url-or-code>` | Redeem an invite link (`…/invite/<code>.md`) or bare code. The human already approved when minting the invite, so there is no verification step — one call and you're connected. The invite URL's origin is persisted as the `api-url`, so follow-up commands target the right server with no flags | — |
119
121
  | `--client-name <name>` | How the CLI appears on the consent screen | `Anima CLI` |
120
122
  | `--no-open` | Don't try to open the verification page in a browser | — |
121
123
  | `--print-mcp-config` | One-shot: after this fresh login, also print the MCP server config. If you are already logged in, use `mcp-config` instead — this flag always starts a new login | off |
@@ -225,15 +227,18 @@ secret, and re-mint rather than store it.
225
227
  npx @animaapp/cli logout
226
228
  ```
227
229
 
228
- Clears **all** stored credentials (Anima token, Figma token, agent metadata) and
229
- removes the config directory. This only forgets the token locally — to actually
230
- disable an agent, revoke it from your team settings.
230
+ A full local reset: clears **all** stored credentials (Anima token, Figma
231
+ token, agent metadata) **and the CLI config** (including an `api-url` persisted
232
+ by `login --invite`) — the machine ends up pristine, as if the CLI was never
233
+ used. This only forgets the token locally — to actually disable an agent,
234
+ revoke it from your team settings.
231
235
 
232
236
  ### `config` — store CLI preferences
233
237
 
234
238
  Persist non-secret settings to `~/.config/anima/config.json` so you don't have to
235
239
  pass flags every time — handy for pointing at a local API during development.
236
- Kept separate from credentials, so `logout` never touches it.
240
+ Note: `logout` removes this file too (full machine reset); `login --invite`
241
+ writes `api-url` automatically from the invite URL's origin.
237
242
 
238
243
  ```bash
239
244
  npx @animaapp/cli config set api-url http://localhost:3789
package/dist/index.js CHANGED
@@ -458,6 +458,15 @@ function setConfig(key, value) {
458
458
  fs3.mkdirSync(CONFIG_DIR2, { recursive: true });
459
459
  fs3.writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + "\n");
460
460
  }
461
+ function deleteConfig() {
462
+ try {
463
+ if (!fs3.existsSync(CONFIG_FILE)) return false;
464
+ fs3.unlinkSync(CONFIG_FILE);
465
+ return true;
466
+ } catch {
467
+ return false;
468
+ }
469
+ }
461
470
  function unsetConfig(key) {
462
471
  const config = readConfig();
463
472
  const field = CONFIG_KEYS[key];
@@ -1062,6 +1071,9 @@ var loginCommand = new Command5("login").description("Log in via the device flow
1062
1071
  const apiUrl2 = opts.apiUrl ? resolveApiUrl(opts.apiUrl) : inviteOrigin ?? resolveApiUrl();
1063
1072
  try {
1064
1073
  const result = await loginWithInvite({ apiUrl: apiUrl2, invite: opts.invite });
1074
+ if (inviteOrigin && readConfig().apiUrl !== apiUrl2) {
1075
+ setConfig("api-url", apiUrl2);
1076
+ }
1065
1077
  const mcpConfig = opts.printMcpConfig ? buildMcpConfig(apiUrl2, result.token) : void 0;
1066
1078
  if (mode === "pretty") {
1067
1079
  printSuccess("Connected!");
@@ -1341,6 +1353,7 @@ import { Command as Command8 } from "commander";
1341
1353
  var logoutCommand = new Command8("logout").description("Clear all stored credentials (Anima + Figma tokens) from this machine").option("--json", "Output as JSON").action((opts) => {
1342
1354
  const mode = detectOutputMode(opts);
1343
1355
  const hadCredentials = clearStorage();
1356
+ deleteConfig();
1344
1357
  if (mode === "pretty") {
1345
1358
  if (hadCredentials) {
1346
1359
  printSuccess("Logged out \u2014 all credentials cleared from " + getCredentialsPath());
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. */\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 } 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 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 { 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\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":";;;AAAA,SAAS,WAAAA,iBAAe;;;ACAxB,SAAS,eAAe;;;ACAxB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAEf,IAAM,aAAa,KAAK,KAAK,GAAG,QAAQ,GAAG,WAAW,OAAO;AAC7D,IAAM,mBAAmB,KAAK,KAAK,YAAY,kBAAkB;AAc1D,SAAS,kBAAsC;AACpD,MAAI;AACF,QAAI,CAAC,GAAG,WAAW,gBAAgB,EAAG,QAAO;AAC7C,UAAM,UAAU,GAAG,aAAa,kBAAkB,OAAO;AACzD,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,QAAI,CAAC,OAAO,MAAO,QAAO;AAC1B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,iBAAiB,aAAyC;AAExE,QAAM,WAAW,gBAAgB,KAAK,CAAC;AACvC,QAAM,SAAS,EAAE,GAAG,UAAU,GAAG,YAAY;AAG7C,aAAW,OAAO,OAAO,KAAK,MAAM,GAA4B;AAC9D,QAAI,OAAO,GAAG,MAAM,OAAW,QAAO,OAAO,GAAG;AAAA,EAClD;AAEA,KAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,KAAG;AAAA,IACD;AAAA,IACA,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI;AAAA,IAClC,EAAE,MAAM,IAAM;AAAA,EAChB;AACF;AAEO,SAAS,oBAA6B;AAC3C,MAAI;AACF,QAAI,GAAG,WAAW,gBAAgB,GAAG;AACnC,SAAG,WAAW,gBAAgB;AAC9B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOO,SAAS,eAAwB;AACtC,QAAM,MAAM,kBAAkB;AAC9B,MAAI;AACF,QAAI,GAAG,WAAW,UAAU,KAAK,GAAG,YAAY,UAAU,EAAE,WAAW,GAAG;AACxE,SAAG,UAAU,UAAU;AAAA,IACzB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,SAAS,qBAA6B;AAC3C,SAAO;AACT;AAMO,SAAS,qBAAqB,OAAmC;AACtE,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,UAAM,UAAU,KAAK;AAAA,MACnB,OAAO,KAAK,MAAM,CAAC,GAAG,WAAW,EAAE,SAAS,OAAO;AAAA,IACrD;AACA,WAAO,QAAQ,iBAAiB;AAAA,EAClC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACjGO,IAAM,aAAa;AAAA,EACxB,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,SAAS;AACX;AAUO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YACE,MACA,SACA,UACA,QACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,SAAS;AAAA,EAChB;AACF;AAEO,SAAS,UAAU,SAA2B;AACnD,SAAO,IAAI,SAAS,iBAAiB,SAAS,WAAW,UAAU;AACrE;AAEO,SAAS,gBAAgB,SAAiB,QAA4B;AAC3E,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,EACF;AACF;AAEO,SAAS,SAAS,SAAiB,QAA4B;AACpE,SAAO,IAAI,SAAS,aAAa,SAAS,WAAW,WAAW,MAAM;AACxE;AAEO,SAAS,eAAyB;AACvC,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACF;;;AC/CO,SAAS,cAA4B;AAC1C,QAAM,QAAQ,gBAAgB;AAG9B,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,UAAU;AACZ,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,QAAQ,IAAI;AAAA,MACpB,YAAY,QAAQ,IAAI,eAAe,OAAO;AAAA,MAC9C,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,MAAI,OAAO;AAGT,QAAI,MAAM,cAAc,WAAW,MAAM,aAAa,IAAI,KAAK,MAAM,SAAS,KAAK,oBAAI,KAAK,GAAG;AAC7F,YAAM,UAAU,gDAAgD;AAAA,IAClE;AACA,WAAO;AAAA,MACL,OAAO,MAAM;AAAA,MACb,QAAQ,MAAM;AAAA,MACd,YAAY,QAAQ,IAAI,eAAe,MAAM;AAAA,MAC7C,QAAQ;AAAA,MACR,WAAW,MAAM;AAAA,IACnB;AAAA,EACF;AAGA,QAAM,UAAU,8EAA8E;AAChG;;;AC3CA,SAAS,cAAc;AACvB,SAAS,qCAAqC;AAC9C,SAAS,sBAAsB,iBAAiB;;;ACFhD,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAYjB,IAAI,UAAyB;AAE7B,IAAM,aAAa;AACnB,IAAM,WAAW;AAEV,SAAS,WAAW,UAAyB;AAClD,QAAM,SAAS,YAAY,QAAQ,IAAI;AACvC,MAAI,CAAC,UAAU,QAAS;AACxB,YAAUA,MAAK,QAAQ,MAAM;AAC7B,EAAAD,IAAG,UAAUC,MAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AACvD,WAAS,eAAe,EAAE,KAAK,QAAQ,KAAK,MAAM,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC;AAC3E;AAEO,SAAS,SAAS,OAAe,MAAsC;AAC5E,MAAI,CAAC,QAAS;AACd,QAAM,QAAQ,EAAE,KAAI,oBAAI,KAAK,GAAE,YAAY,GAAG,OAAO,GAAI,OAAO,OAAO,IAAI,IAAI,CAAC,EAAG;AACnF,EAAAD,IAAG,eAAe,SAAS,KAAK,UAAU,KAAK,IAAI,IAAI;AACzD;AAEA,SAAS,OAAO,OAAyD;AACvE,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,QAAI,WAAW,KAAK,GAAG,GAAG;AACxB,UAAI,GAAG,IAAI;AAAA,IACb,WAAW,OAAO,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,GAAG;AAChE,UAAI,GAAG,IAAI,OAAO,GAA8B;AAAA,IAClD,OAAO;AACL,UAAI,GAAG,IAAI;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;;;AC5CA,SAAS,qBAAqB;AAKvB,IAAM,EAAE,QAAQ,IAAI,cAAc,YAAY,GAAG,EAAE,iBAAiB;;;AFQ3E,IAAM,WAAW;AAEjB,IAAM,cAAc,EAAE,MAAM,aAAa,QAAQ;AAmBjD,IAAM,qBAAqB;AAEpB,IAAM,iBAAN,MAAqB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,QAAmB;AAC7B,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,OAAO,KAAK;AAAA,IACvC;AACA,QAAI,OAAO,OAAQ,SAAQ,WAAW,IAAI,OAAO;AACjD,QAAI,OAAO,WAAY,SAAQ,eAAe,IAAI,OAAO;AAEzD,SAAK,OAAO,IAAI,IAAI,UAAU,OAAO,UAAU,EAAE,SAAS;AAC1D,SAAK,aAAa,IAAI,8BAA8B,IAAI,IAAI,KAAK,IAAI,GAAG;AAAA,MACtE,aAAa,EAAE,QAAQ;AAAA,IACzB,CAAC;AACD,SAAK,UAAU,IAAI,OAAO,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,UAAyB;AAC7B,aAAS,eAAe,EAAE,KAAK,KAAK,KAAK,CAAC;AAC1C,QAAI;AACF,YAAM,KAAK,QAAQ,QAAQ,KAAK,UAAU;AAAA,IAC5C,SAAS,KAAK;AACZ,eAAS,sBAAsB,EAAE,KAAK,KAAK,MAAM,OAAQ,KAAe,QAAQ,CAAC;AACjF,YAAM,gBAAgB,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SACJ,MACA,MACA,UAA2B,CAAC,GAChB;AACZ,aAAS,iBAAiB,EAAE,MAAM,MAAM,WAAW,KAAK,CAAC;AACzD,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,KAAK,QAAQ;AAAA,QAC1B,EAAE,MAAM,WAAW,KAAK;AAAA,QACxB;AAAA,QACA;AAAA,UACE,SAAS,QAAQ,aAAa;AAAA,UAC9B,wBAAwB;AAAA,UACxB,YAAY,QAAQ,aAChB,CAAC,MAAM,QAAQ,WAAY,EAAE,UAAU,EAAE,UAAU,OAAO,EAAE,OAAO,SAAS,EAAE,QAAQ,CAAC,IACvF;AAAA,QACN;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,eAAS,kBAAkB,EAAE,MAAM,MAAM,OAAQ,KAAe,QAAQ,CAAC;AACzE,UAAK,KAA2B,SAAS,UAAU,gBAAgB;AACjE,cAAM,aAAa;AAAA,MACrB;AACA,YAAM;AAAA,IACR;AACA,aAAS,mBAAmB,EAAE,MAAM,MAAM,SAAS,OAAO,WAAW,MAAM,CAAC;AAE5E,UAAM,UAAU,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;AAClE,UAAM,OAAO,QAAQ,KAAK,CAAC,MAA2C,EAAE,SAAS,MAAM,GAAG;AAE1F,QAAI,OAAO,SAAS;AAClB,YAAM,SAAS,QAAQ,4BAA4B;AAAA,IACrD;AACA,QAAI,CAAC,MAAM;AACT,YAAM,SAAS,mCAAmC;AAAA,IACpD;AAEA,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,WAAW,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC9C;AACF;AAGA,eAAsB,QACpB,QACA,IACY;AACZ,QAAM,SAAS,IAAI,eAAe,MAAM;AACxC,QAAM,OAAO,QAAQ;AACrB,MAAI;AACF,WAAO,MAAM,GAAG,MAAM;AAAA,EACxB,UAAE;AACA,UAAM,OAAO,MAAM;AAAA,EACrB;AACF;AAEA,SAAS,gBAAgB,KAAwB;AAC/C,QAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,SAAO,IAAI;AAAA,IACT;AAAA,IACA,2CAA2C,OAAO;AAAA,IAClD;AAAA,EACF;AACF;;;AG3IO,SAAS,iBAAiB,OAElB;AACb,MAAI,MAAM,SAAS,QAAW;AAC5B,WAAO,MAAM,OAAO,SAAS;AAAA,EAC/B;AAEA,SAAO,QAAQ,OAAO,QAAQ,WAAW;AAC3C;AAEO,SAAS,aAAa,MAAkB,MAAqB;AAClE,MAAI,SAAS,QAAQ;AACnB,YAAQ,OAAO,MAAM,KAAK,UAAU,IAAI,IAAI,IAAI;AAAA,EAClD;AAEF;AAEO,SAAS,YACd,MACA,OACM;AACN,MAAI,SAAS,QAAQ;AACnB,YAAQ,OAAO;AAAA,MACb,KAAK,UAAU,EAAE,SAAS,OAAO,MAAM,CAAC,IAAI;AAAA,IAC9C;AAAA,EACF;AAEF;;;AC7BA,OAAO,SAAuB;AAGvB,IAAM,mBAAN,MAAuB;AAAA,EAC5B,WAAuB;AAAA,EACvB;AAAA,EACA,aAAqB;AAAA,EACrB;AAAA,EAEA,YAAY,MAAkB,UAAmB,OAAO;AACtD,SAAK,QAAQ;AACb,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAM,SAAuB;AAC3B,SAAK,aAAa,KAAK,IAAI;AAC3B,QAAI,KAAK,UAAU,UAAU;AAC3B,WAAK,WAAW,IAAI,OAAO,EAAE,MAAM;AAAA,IACrC,WAAW,KAAK,UAAU;AACxB,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,QAAQ,WAAW,QAAQ,CAAC,IAAI,IAAI;AAAA,IAC5E;AAAA,EACF;AAAA,EAEA,OAAO,SAAuB;AAC5B,QAAI,KAAK,UAAU,YAAY,KAAK,UAAU;AAC5C,YAAM,UAAU,KAAK,SAAS;AAC9B,WAAK,SAAS,OAAO,GAAG,OAAO,IAAI,OAAO;AAAA,IAC5C,WAAW,KAAK,UAAU;AACxB,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,QAAQ,YAAY,QAAQ,CAAC,IAAI,IAAI;AAAA,IAC7E;AAAA,EACF;AAAA,EAEA,QAAQ,SAAuB;AAC7B,QAAI,KAAK,UAAU,YAAY,KAAK,UAAU;AAC5C,YAAM,UAAU,KAAK,SAAS;AAC9B,WAAK,SAAS,QAAQ,GAAG,OAAO,IAAI,OAAO,EAAE;AAAA,IAC/C,WAAW,KAAK,UAAU;AACxB,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,QAAQ,QAAQ,QAAQ,CAAC,IAAI,IAAI;AAAA,IACzE;AACA,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,KAAK,SAAuB;AAC1B,QAAI,KAAK,UAAU,YAAY,KAAK,UAAU;AAC5C,WAAK,SAAS,KAAK,OAAO;AAAA,IAC5B,WAAW,KAAK,UAAU;AACxB,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,QAAQ,SAAS,QAAQ,CAAC,IAAI,IAAI;AAAA,IAC1E;AACA,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,WAAmB;AACjB,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK;AAC7B,UAAM,UAAU,KAAK,MAAM,KAAK,GAAI;AACpC,QAAI,UAAU,GAAI,QAAO,IAAI,OAAO;AACpC,UAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,UAAM,OAAO,UAAU;AACvB,WAAO,IAAI,OAAO,KAAK,IAAI;AAAA,EAC7B;AACF;;;AC3DA,OAAO,WAAW;AAEX,SAAS,aAAa,SAAuB;AAClD,UAAQ,IAAI,MAAM,MAAM,QAAG,IAAI,MAAM,OAAO;AAC9C;AAEO,SAAS,WAAW,SAAuB;AAChD,UAAQ,MAAM,MAAM,IAAI,QAAG,IAAI,MAAM,OAAO;AAC9C;AAEO,SAAS,UAAU,SAAuB;AAC/C,UAAQ,IAAI,MAAM,KAAK,QAAG,IAAI,MAAM,OAAO;AAC7C;AAMO,SAAS,cAAc,KAAa,OAAqB;AAC9D,UAAQ,IAAI,KAAK,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,KAAK,EAAE;AACnD;AAEO,SAAS,mBAAmB,QAI1B;AACP,UAAQ,IAAI;AACZ,eAAa,kCAAkC;AAC/C,gBAAc,cAAc,OAAO,SAAS;AAC5C,MAAI,OAAO,eAAe;AACxB,kBAAc,cAAc,MAAM,KAAK,UAAU,OAAO,aAAa,CAAC;AAAA,EACxE;AACA,MAAI,OAAO,YAAY;AACrB,kBAAc,eAAe,OAAO,WAAW,eAAe,CAAC;AAAA,EACjE;AACA,UAAQ,IAAI;AACd;AAEO,SAAS,kBAAkB,QAKzB;AACP,UAAQ,IAAI;AACZ,eAAa,yBAAyB;AACtC,MAAI,OAAO,KAAK;AACd,kBAAc,YAAY,MAAM,KAAK,UAAU,OAAO,GAAG,CAAC;AAAA,EAC5D;AACA,MAAI,OAAO,aAAa;AACtB,kBAAc,WAAW,OAAO,WAAW;AAC3C,kBAAc,WAAW,OAAO,kBAAkB,EAAE;AACpD,QAAI,OAAO,YAAY;AACrB,oBAAc,OAAO,MAAM,KAAK,UAAU,OAAO,UAAU,CAAC;AAAA,IAC9D;AAAA,EACF;AACA,UAAQ,IAAI;AACd;AAEO,SAAS,kBAAkB,WAAmB,OAAqB;AACxE,UAAQ,IAAI;AACZ,eAAa,GAAG,KAAK,qBAAqB,MAAM,KAAK,SAAS,CAAC,EAAE;AACjE,UAAQ,IAAI;AACd;;;ACvDO,SAAS,cAAc,OAG5B;AAEA,MAAI,CAAC,MAAM,SAAS,WAAW,GAAG;AAChC,WAAO,EAAE,SAAS,MAAM;AAAA,EAC1B;AAEA,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,YAAY,IAAI,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAGxD,UAAM,YAAY,UAAU;AAAA,MAC1B,CAAC,MAAM,MAAM,UAAU,MAAM;AAAA,IAC/B;AACA,QAAI,cAAc,MAAM,YAAY,KAAK,UAAU,QAAQ;AACzD,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAEA,UAAM,UAAU,UAAU,YAAY,CAAC;AACvC,UAAM,cAAc,IAAI,aAAa,IAAI,SAAS;AAElD,QAAI;AACJ,QAAI,aAAa;AAEf,eAAS,YAAY,QAAQ,MAAM,GAAG;AAAA,IACxC;AAEA,WAAO,EAAE,SAAS,OAAO;AAAA,EAC3B,SAAS,KAAK;AACZ,QAAI,eAAe,SAAS,IAAI,QAAQ,SAAS,UAAU,GAAG;AAC5D,YAAM;AAAA,IACR;AACA,UAAM,IAAI,MAAM,sBAAsB,KAAK,EAAE;AAAA,EAC/C;AACF;AAMO,SAAS,gBAAgB,QAAwB;AACtD,SAAO,OAAO,QAAQ,MAAM,GAAG;AACjC;;;ACtDA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AAQf,IAAMC,cAAaF,MAAK,KAAKC,IAAG,QAAQ,GAAG,WAAW,OAAO;AAC7D,IAAM,cAAcD,MAAK,KAAKE,aAAY,aAAa;AAEhD,IAAM,kBAAkB;AAOxB,IAAM,cAAc;AAAA,EACzB,WAAW;AACb;AAIO,SAAS,YAAY,KAA+B;AACzD,SAAO,OAAO;AAChB;AAEO,SAAS,aAA0B;AACxC,SAAO,OAAO,KAAK,WAAW;AAChC;AAEO,SAAS,aAAqB;AACnC,MAAI;AACF,QAAI,CAACH,IAAG,WAAW,WAAW,EAAG,QAAO,CAAC;AACzC,UAAM,SAAS,KAAK,MAAMA,IAAG,aAAa,aAAa,OAAO,CAAC;AAC/D,WAAO,UAAU,OAAO,WAAW,WAAW,SAAS,CAAC;AAAA,EAC1D,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,UAAU,KAAgB,OAAqB;AAC7D,QAAM,SAAS,EAAE,GAAG,WAAW,GAAG,CAAC,YAAY,GAAG,CAAC,GAAG,MAAM;AAC5D,EAAAA,IAAG,UAAUG,aAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,EAAAH,IAAG,cAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AACtE;AAGO,SAAS,YAAY,KAAyB;AACnD,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,YAAY,GAAG;AAC7B,MAAI,EAAE,SAAS,QAAS,QAAO;AAC/B,SAAO,OAAO,KAAK;AACnB,EAAAA,IAAG,UAAUG,aAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,EAAAH,IAAG,cAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AACpE,SAAO;AACT;AAEO,SAAS,gBAAwB;AACtC,SAAO;AACT;AAMO,SAAS,cAAc,WAA4B;AACxD,SAAO,aAAa,QAAQ,IAAI,iBAAiB,WAAW,EAAE,UAAU;AAC1E;;;AX3DA,IAAM,kBAAkB;AAgBjB,IAAM,gBAAgB,IAAI,QAAQ,QAAQ,EAC9C,YAAY,+FAA+F,EAC3G,eAAe,qBAAqB,yFAAoF,EACxH,OAAO,yBAAyB,mBAAmB,EACnD,OAAO,mBAAmB,mBAAmB,EAC7C,OAAO,oBAAoB,6BAA6B,EACxD,OAAO,mBAAmB,uCAAuC,EACjE,OAAO,yBAAyB,mCAAmC,EACnE,OAAO,oBAAoB,mEAA8D,EACzF,OAAO,qBAAqB,4DAA4D,UAAU,EAClG,OAAO,qBAAqB,yBAAyB,EACrD,OAAO,sBAAsB,mCAAmC,EAChE,OAAO,uBAAuB,mCAAmC,EACjE,OAAO,iBAAiB,2BAA2B,EACnD,OAAO,UAAU,gBAAgB,EACjC,OAAO,kBAAkB,2BAA2B,QAAQ,EAC5D,OAAO,aAAa,yBAAyB,EAC7C,OAAO,mBAAmB,iDAAiD,EAC3E,OAAO,qBAAqB,mDAAmD,EAC/E,OAAO,OAAO,SAAS;AACtB,QAAM,OAAO,iBAAiB,IAAI;AAClC,aAAW,KAAK,OAAO;AACvB,QAAM,WAAW,IAAI,iBAAiB,MAAM,KAAK,OAAO;AAExD,MAAI;AACF,UAAM,OAAO,KAAK;AAClB,0BAAsB,MAAM,IAAI;AAEhC,UAAM,OAAO,YAAY;AACzB,UAAM,aAAa,SAAS,QAAQ,kBAAkB,MAAM,KAAK,UAAU,IAAI;AAC/E,UAAM,OAAO,gBAAgB,MAAM,IAAI;AAEvC,aAAS,MAAM,SAAS,UAAU,iCAAiC,YAAY,KAAK,YAAY,CAAC,gBAAgB;AAEjH,UAAM,SAAS,MAAM;AAAA,MACnB,EAAE,YAAY,cAAc,KAAK,MAAM,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,WAAW;AAAA,MAC7F,CAAC,WACC,OAAO,SAAuB,qBAAqB,MAAM;AAAA,QACvD,WAAW,SAAS,KAAK,SAAS,EAAE;AAAA,QACpC,YAAY,CAAC,MAAM,SAAS,OAAO,EAAE,WAAW,eAAe,KAAK,MAAM,EAAE,QAAQ,CAAC,OAAO;AAAA,MAC9F,CAAC;AAAA,IACL;AAEA,QAAI,CAAC,OAAO,WAAW,CAAC,OAAO,WAAW;AACxC,YAAM,SAAS,OAAO,UAAU,OAAO,SAAS,qBAAqB,MAAM;AAAA,IAC7E;AAEA,UAAM,gBAAgB,OAAO,iBAAiB,GAAG,eAAe,IAAI,OAAO,SAAS;AAEpF,aAAS,QAAQ,qBAAqB;AAEtC,QAAI,SAAS,UAAU;AACrB,yBAAmB,EAAE,WAAW,OAAO,WAAW,cAAc,CAAC;AACjE,UAAI,OAAO,cAAc;AACvB,gBAAQ,IAAI,eAAe,OAAO,YAAY,EAAE;AAChD,gBAAQ,IAAI;AACZ,gBAAQ;AAAA,UACN,gGACW,OAAO,YAAY,aAAa,OAAO,SAAS,MAAM,EAAE,8CACrC,OAAO,SAAS;AAAA,QAChD;AACA,gBAAQ,IAAI;AAAA,MACd,WAAW,SAAS,SAAS;AAC3B,gBAAQ;AAAA,UACN,+BAA+B,OAAO,SAAS;AAAA,QACjD;AACA,gBAAQ,IAAI;AAAA,MACd;AAAA,IACF,OAAO;AACL,mBAAa,MAAM;AAAA,QACjB,SAAS;AAAA,QACT,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,GAAI,OAAO,eACP,EAAE,cAAc,OAAO,cAAc,QAAQ,OAAO,QAAQ,WAAW,OAAO,UAAU,IACxF,CAAC;AAAA,QACL,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,MAC5D,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,aAAS,KAAK,QAAQ;AACtB,QAAI,eAAe,UAAU;AAC3B,UAAI,SAAS,UAAU;AACrB,gBAAQ,MAAM,IAAI,OAAO;AAAA,MAC3B,OAAO;AACL,oBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,UAAM;AAAA,EACR;AACF,CAAC;AAEH,SAAS,sBAAsB,MAAkB,MAAoC;AACnF,MAAI,CAAC,CAAC,OAAO,OAAO,OAAO,OAAO,EAAE,SAAS,IAAI,GAAG;AAClD,UAAM,gBAAgB,iBAAiB,IAAI,qCAAqC;AAAA,EAClF;AACA,MAAI,SAAS,SAAS,CAAC,KAAK,QAAQ;AAClC,UAAM,gBAAgB,mCAAmC;AAAA,EAC3D;AACA,MAAI,SAAS,SAAS,CAAC,KAAK,KAAK;AAC/B,UAAM,gBAAgB,gCAAgC;AAAA,EACxD;AACA,MAAI,SAAS,SAAS,CAAC,KAAK,SAAS;AACnC,UAAM,gBAAgB,qCAAqC;AAAA,EAC7D;AACF;AAEA,SAAS,kBAAkB,MAA8B,QAAyB;AAChF,QAAM,aAAa,KAAK,cAAc,QAAQ,IAAI,eAAe;AACjE,MAAI,CAAC,YAAY;AACf,UAAM;AAAA,MACJ;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,MAAkB,MAAuD;AAIhG,QAAM,YAAY,KAAK,aAAa;AACpC,MAAI,SAAS,SAAS;AACpB,WAAO,EAAE,MAAM,WAAW,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC,EAAG;AAAA,EACtE;AAEA,QAAM,WAAW,KAAK,aAAa,cAAc,UAAU,eAAe;AAE1E,QAAM,OAAgC;AAAA,IACpC;AAAA,IACA;AAAA,IACA,SAAS,KAAK;AAAA,EAChB;AACA,MAAI,SAAU,MAAK,WAAW;AAC9B,MAAI,KAAK,UAAW,MAAK,YAAY,KAAK;AAE1C,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,WAAK,SAAS,KAAK;AACnB,UAAI,KAAK,WAAY,MAAK,aAAa,KAAK;AAC5C;AAAA,IACF,KAAK;AACH,WAAK,MAAM,KAAK;AAChB;AAAA,IACF,KAAK,OAAO;AACV,YAAM,EAAE,SAAS,QAAQ,aAAa,IAAI,cAAc,KAAK,OAAO;AACpE,UAAI,UAAoB,CAAC;AACzB,UAAI,KAAK,OAAO;AACd,kBAAU,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,gBAAgB,EAAE,KAAK,CAAC,CAAC;AAAA,MACtE,WAAW,cAAc;AACvB,kBAAU,CAAC,YAAY;AAAA,MACzB;AACA,WAAK,UAAU;AACf,WAAK,UAAU;AACf;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AY7LA,SAAS,WAAAI,gBAAe;AAUjB,IAAM,iBAAiB,IAAIC,SAAQ,SAAS,EAChD,YAAY,wDAAwD,EACpE,SAAS,eAAe,gCAAgC,EACxD,OAAO,iBAAiB,yBAAyB,QAAQ,EACzD,OAAO,yBAAyB,sCAAsC,EACtE,OAAO,+BAA+B,yCAAyC,EAC/E,OAAO,UAAU,gBAAgB,EACjC,OAAO,aAAa,yBAAyB,EAC7C,OAAO,mBAAmB,iDAAiD,EAC3E,OAAO,qBAAqB,mDAAmD,EAC/E,OAAO,OAAO,WAAmB,SAAS;AACzC,QAAM,OAAO,iBAAiB,IAAI;AAClC,aAAW,KAAK,OAAO;AACvB,QAAM,WAAW,IAAI,iBAAiB,MAAM,KAAK,OAAO;AAExD,MAAI;AACF,QAAI,CAAC,CAAC,UAAU,cAAc,EAAE,SAAS,KAAK,IAAI,GAAG;AACnD,YAAM;AAAA,QACJ,iBAAiB,KAAK,IAAI;AAAA,MAC5B;AAAA,IACF;AAEA,QAAI,KAAK,SAAS,kBAAkB,CAAC,KAAK,aAAa;AACrD,YAAM,gBAAgB,kDAAkD;AAAA,IAC1E;AAEA,UAAM,OAAO,YAAY;AAEzB,UAAM,OAAgC;AAAA,MACpC;AAAA,MACA,MAAM,KAAK;AAAA,IACb;AACA,QAAI,KAAK,YAAa,MAAK,cAAc,KAAK;AAC9C,QAAI,KAAK,eAAgB,MAAK,iBAAiB,KAAK;AAEpD,aAAS,MAAM,iBAAiB,KAAK,IAAI,KAAK;AAE9C,UAAM,SAAS,MAAM;AAAA,MACnB,EAAE,YAAY,cAAc,KAAK,MAAM,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,MACjF,CAAC,WACC,OAAO,SAAkC,sBAAsB,MAAM;AAAA,QACnE,YAAY,CAAC,MAAM,SAAS,OAAO,EAAE,WAAW,eAAe;AAAA,MACjE,CAAC;AAAA,IACL;AAEA,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,QACC,OAAO,SAAqB,OAAO,UAAqB;AAAA,QACzD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,aAAS,QAAQ,YAAY;AAE7B,QAAI,SAAS,UAAU;AACrB,wBAAkB;AAAA,QAChB,KAAK,OAAO;AAAA,QACZ,YAAY,OAAO;AAAA,QACnB,aAAa,OAAO;AAAA,QACpB,gBAAgB,OAAO;AAAA,MACzB,CAAC;AAAA,IACH,OAAO;AACL,mBAAa,MAAM;AAAA,QACjB,SAAS;AAAA,QACT;AAAA,QACA,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,QACjF,GAAI,OAAO,cACP;AAAA,UACE,aAAa,OAAO;AAAA,UACpB,gBAAgB,OAAO;AAAA,UACvB,YAAY,OAAO;AAAA,QACrB,IACA,CAAC;AAAA,MACP,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,aAAS,KAAK,QAAQ;AACtB,QAAI,eAAe,UAAU;AAC3B,UAAI,SAAS,UAAU;AACrB,gBAAQ,MAAM,IAAI,OAAO;AAAA,MAC3B,OAAO;AACL,oBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,UAAM;AAAA,EACR;AACF,CAAC;;;ACnGH,SAAS,WAAAC,gBAAe;;;ACAxB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAOV,SAAS,iBACd,OACA,WACQ;AAER,EAAAD,IAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAE3C,MAAI,QAAQ;AAEZ,QAAM,iBAAiBC,MAAK,QAAQ,SAAS;AAE7C,aAAW,CAAC,UAAU,WAAW,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC3D,UAAM,WAAWA,MAAK,QAAQ,WAAW,QAAQ;AAEjD,QAAI,CAAC,SAAS,WAAW,iBAAiBA,MAAK,GAAG,GAAG;AACnD,YAAM,IAAI,MAAM,4BAA4B,QAAQ,EAAE;AAAA,IACxD;AAGA,UAAM,UAAUA,MAAK,QAAQ,QAAQ;AACrC,IAAAD,IAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAEzC,QAAI,YAAY,UAAU;AACxB,YAAM,SAAS,OAAO,KAAK,YAAY,SAAS,QAAQ;AACxD,MAAAA,IAAG,cAAc,UAAU,MAAM;AAAA,IACnC,OAAO;AACL,MAAAA,IAAG,cAAc,UAAU,YAAY,SAAS,OAAO;AAAA,IACzD;AAEA;AAAA,EACF;AAEA,SAAO;AACT;;;ADnBO,IAAM,iBAAiB,IAAIE,SAAQ,SAAS,EAChD,YAAY,oDAAoD,EAChE,eAAe,oBAAoB,uBAAuB,EAC1D,OAAO,mBAAmB,iCAAiC,EAC3D,OAAO,yBAAyB,0DAA0D,EAC1F,OAAO,sBAAsB,oBAAoB,aAAa,EAC9D,OAAO,oBAAoB,gBAAgB,OAAO,EAClD,OAAO,qBAAqB,wBAAwB,UAAU,EAC9D,OAAO,qBAAqB,yBAAyB,EACrD,OAAO,sBAAsB,mCAAmC,EAChE,OAAO,UAAU,gBAAgB,EACjC,OAAO,kBAAkB,2BAA2B,QAAQ,EAC5D,OAAO,aAAa,yBAAyB,EAC7C,OAAO,mBAAmB,iDAAiD,EAC3E,OAAO,qBAAqB,mDAAmD,EAC/E,OAAO,OAAO,SAAS;AACtB,QAAM,OAAO,iBAAiB,IAAI;AAClC,aAAW,KAAK,OAAO;AACvB,QAAM,WAAW,IAAI,iBAAiB,MAAM,KAAK,OAAO;AAExD,MAAI;AACF,UAAM,EAAE,SAAS,QAAQ,aAAa,IAAI,cAAc,KAAK,OAAO;AACpE,QAAI,UAAoB,CAAC;AACzB,QAAI,KAAK,OAAO;AACd,gBAAU,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,gBAAgB,EAAE,KAAK,CAAC,CAAC;AAAA,IAC9E,WAAW,cAAc;AACvB,gBAAU,CAAC,YAAY;AAAA,IACzB;AAEA,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,YAAY;AAIzB,UAAM,aAAa,KAAK,cAAc,QAAQ,IAAI,eAAe,KAAK;AACtE,QAAI,CAAC,YAAY;AACf,YAAM;AAAA,QACJ;AAAA,MAEF;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,aAAa,KAAK,cAAc,UAAU,eAAe;AAE/E,UAAM,OAAgC;AAAA,MACpC;AAAA,MACA;AAAA,MACA,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,IAChB;AACA,QAAI,SAAU,MAAK,WAAW;AAC9B,QAAI,KAAK,UAAW,MAAK,YAAY,KAAK;AAE1C,aAAS,MAAM,+BAA+B;AAE9C,UAAM,SAAS,MAAM;AAAA,MACnB,EAAE,YAAY,cAAc,KAAK,MAAM,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,WAAW;AAAA,MAC7F,CAAC,WACC,OAAO,SAAwB,yBAAyB,MAAM;AAAA,QAC5D,WAAW,SAAS,KAAK,SAAS,EAAE;AAAA,QACpC,YAAY,CAAC,MAAM,SAAS,OAAO,EAAE,WAAW,eAAe,KAAK,MAAM,EAAE,QAAQ,CAAC,OAAO;AAAA,MAC9F,CAAC;AAAA,IACL;AAEA,QAAI,CAAC,OAAO,WAAW,CAAC,OAAO,OAAO;AACpC,YAAM,SAAS,OAAO,UAAU,OAAO,SAAS,0BAA0B,MAAM;AAAA,IAClF;AAEA,UAAM,QAAQ,iBAAiB,OAAO,OAAO,KAAK,MAAM;AAExD,aAAS,QAAQ,aAAa,KAAK,QAAQ;AAE3C,QAAI,SAAS,UAAU;AACrB,wBAAkB,KAAK,QAAQ,KAAK;AAAA,IACtC,OAAO;AACL,mBAAa,MAAM;AAAA,QACjB,SAAS;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,WAAW;AAAA,QACX,WAAW,OAAO;AAAA,QAClB,YAAY,OAAO;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,aAAS,KAAK,QAAQ;AACtB,QAAI,eAAe,UAAU;AAC3B,UAAI,SAAS,UAAU;AACrB,gBAAQ,MAAM,IAAI,OAAO;AAAA,MAC3B,OAAO;AACL,oBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,UAAM;AAAA,EACR;AACF,CAAC;;;AE3HH,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;;;ACKX,SAAS,mBAAmB,OAAuB;AACxD,MAAI,CAAC,MAAM,SAAS,GAAG,GAAG;AACxB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,QAAQ,IAAI,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAEpD,UAAM,YAAY,MAAM,QAAQ,MAAM;AACtC,QAAI,cAAc,MAAM,YAAY,IAAI,MAAM,QAAQ;AACpD,aAAO,MAAM,YAAY,CAAC;AAAA,IAC5B;AAEA,WAAO,MAAM,MAAM,SAAS,CAAC;AAAA,EAC/B,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;;;ACRA,SAAS,QAAQ,SAA0B;AACzC,QAAM,OAAO,OAAO,YAAY,WAAW,UAAU,KAAK,UAAU,OAAO;AAC3E,UAAQ,QAAQ,OAAO,OAAO,GAAG,MAAM,GAAG,GAAG;AAC/C;AAEO,SAAS,sBAAsB,SAAiC;AACrE,MAAI,QAAQ;AACZ,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI;AACF,cAAQ,KAAK,MAAM,KAAK;AAAA,IAC1B,QAAQ;AACN,YAAM,SAAS,mDAAmD,QAAQ,OAAO,CAAC,EAAE;AAAA,IACtF;AAAA,EACF;AAEA,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,UAAM,SAAS,mDAAmD,QAAQ,OAAO,CAAC,EAAE;AAAA,EACtF;AAEA,QAAM,OAAO;AASb,MAAI,KAAK,YAAY,OAAO;AAC1B,UAAM,SAAS,cAAc,KAAK,SAAS,QAAQ,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,EAAE;AAAA,EACtF;AAEA,MAAI,CAAC,KAAK,cAAc;AACtB,UAAM,SAAS,mDAAmD,QAAQ,OAAO,CAAC,EAAE;AAAA,EACtF;AAEA,SAAO;AAAA,IACL,cAAc,KAAK;AAAA,IACnB,QAAQ,KAAK,WAAW,OAAO,OAAO;AAAA,IACtC,WAAW,KAAK;AAAA,EAClB;AACF;;;AFlCO,IAAM,qBAAqB,IAAIC,SAAQ,eAAe,EAC1D,YAAY,0EAA0E,EACtF,SAAS,mBAAmB,8BAA8B,EAC1D,OAAO,UAAU,gBAAgB,EACjC,OAAO,aAAa,yBAAyB,EAC7C,OAAO,mBAAmB,iDAAiD,EAC3E,OAAO,qBAAqB,mDAAmD,EAC/E,OAAO,OAAO,eAAuB,SAAS;AAC7C,QAAM,OAAO,iBAAiB,IAAI;AAClC,aAAW,KAAK,OAAO;AACvB,QAAM,WAAW,IAAI,iBAAiB,MAAM,KAAK,OAAO;AAExD,MAAI;AACF,UAAM,YAAY,mBAAmB,aAAa;AAClD,UAAM,OAAO,YAAY;AAEzB,aAAS,MAAM,0BAA0B;AAEzC,UAAM,WAAW,MAAM;AAAA,MACrB,EAAE,YAAY,cAAc,KAAK,MAAM,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,MACjF,CAAC,WACC,OAAO,SAAkB,yBAAyB,EAAE,UAAU,CAAC;AAAA,IACnE;AAEA,UAAM,QAAQ,sBAAsB,QAAQ;AAC5C,aAAS,qBAAqB,EAAE,WAAW,QAAQ,MAAM,QAAQ,WAAW,MAAM,UAAU,CAAC;AAE7F,aAAS,QAAQ,uBAAuB,MAAM,WAAW,OAAO,eAAe,WAAW,GAAG;AAE7F,QAAI,SAAS,UAAU;AACrB,cAAQ,IAAI;AACZ,cAAQ,IAAI,KAAKC,OAAM,KAAK,aAAa,MAAM,YAAY,EAAE,CAAC,EAAE;AAChE,cAAQ,IAAI;AACZ,UAAI,MAAM,WAAW,MAAM;AACzB,gBAAQ,IAAI,kDAAkD;AAAA,MAChE,OAAO;AACL,gBAAQ,IAAI,uDAAuD;AAAA,MACrE;AACA,UAAI,MAAM,WAAW;AACnB,gBAAQ;AAAA,UACN,4CAA4C,MAAM,SAAS;AAAA,4BAC5BA,OAAM,KAAK,qCAAqC,CAAC;AAAA,QAClF;AAAA,MACF;AACA,cAAQ,IAAI,yEAAoE;AAChF,cAAQ,IAAI;AAAA,IACd,OAAO;AACL,mBAAa,MAAM;AAAA,QACjB,SAAS;AAAA,QACT;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,QAAQ,MAAM;AAAA,QACd,WAAW,MAAM;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,aAAS,KAAK,QAAQ;AACtB,QAAI,eAAe,UAAU;AAC3B,UAAI,SAAS,UAAU;AACrB,gBAAQ,MAAM,IAAI,OAAO;AAAA,MAC3B,OAAO;AACL,oBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,UAAM;AAAA,EACR;AACF,CAAC;;;AG3FH,SAAS,WAAAC,gBAAe;;;ACAxB,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAClB,OAAO,UAAU;;;ACejB,IAAM,oBAAoB;AAC1B,IAAM,sBAAsB;AA0B5B,IAAM,eAAe,CAAC,OAAe,IAAI,QAAc,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAG3F,SAAS,iBAAiB,OAAoD;AAC5E,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,WAAO,KAAK,MAAM,OAAO,KAAK,MAAM,CAAC,GAAG,WAAW,EAAE,SAAS,OAAO,CAAC;AAAA,EACxE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,oBAAoB,SAAyD;AACjG,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,QAAQ,QAAQ,WAAW;AACjC,QAAM,OAAO,QAAQ,OAAO,QAAQ,OAAO,EAAE;AAI7C,QAAM,WAAW,GAAG,IAAI;AACxB,WAAS,gCAAgC,EAAE,KAAK,SAAS,CAAC;AAC1D,QAAM,gBAAgB,MAAM,QAAQ,UAAU;AAAA,IAC5C,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,IAC/D,MAAM,IAAI,gBAAgB,EAAE,aAAa,QAAQ,cAAc,oBAAoB,CAAC,EAAE,SAAS;AAAA,EACjG,CAAC;AACD,WAAS,iCAAiC,EAAE,KAAK,UAAU,QAAQ,cAAc,OAAO,CAAC;AAEzF,MAAI,CAAC,cAAc,IAAI;AACrB,UAAM,SAAS,MAAM,cAAc,KAAK,EAAE,MAAM,MAAM,EAAE;AACxD,aAAS,+BAA+B,EAAE,KAAK,UAAU,QAAQ,cAAc,QAAQ,MAAM,OAAO,MAAM,GAAG,GAAG,EAAE,CAAC;AACnH,UAAM,OACJ,cAAc,WAAW,MACrB,iCAA4B,QAAQ,2EACpC;AACN,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qCAAqC,cAAc,MAAM,IAAI,IAAI;AAAA,MACjE,WAAW;AAAA,IACb;AAAA,EACF;AAEA,QAAM,QAAS,MAAM,cAAc,KAAK;AASxC,UAAQ,eAAe;AAAA,IACrB,UAAU,MAAM;AAAA,IAChB,iBAAiB,MAAM;AAAA,IACvB,yBAAyB,MAAM;AAAA,IAC/B,kBAAkB,MAAM;AAAA,EAC1B,CAAC;AAID,MAAI,aAAa,KAAK,IAAI,GAAG,MAAM,QAAQ,IAAI;AAC/C,QAAM,WAAW,KAAK,IAAI,IAAI,MAAM,aAAa;AAEjD,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,MAAM,UAAU;AAEtB,UAAM,eAAe,MAAM,QAAQ,GAAG,IAAI,gBAAgB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,MAC/D,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,aAAa,MAAM;AAAA,MACrB,CAAC,EAAE,SAAS;AAAA,IACd,CAAC;AAED,UAAM,OAAQ,MAAM,aAAa,KAAK;AACtC,aAAS,qBAAqB,EAAE,QAAQ,aAAa,QAAQ,OAAO,KAAK,MAAM,CAAC;AAEhF,QAAI,aAAa,MAAM,OAAO,KAAK,iBAAiB,UAAU;AAC5D,YAAM,QAAQ,KAAK;AACnB,YAAM,SAAS,iBAAiB,KAAK;AACrC,YAAM,SAA4B;AAAA,QAChC;AAAA,QACA,QAAQ,OAAO,QAAQ,YAAY,WAAW,OAAO,UAAU;AAAA,QAC/D,SAAS,OAAO,QAAQ,aAAa,WAAW,OAAO,WAAW;AAAA,QAClE,WACE,OAAO,QAAQ,QAAQ,WAAW,IAAI,KAAK,OAAO,MAAM,GAAI,EAAE,YAAY,IAAI;AAAA,MAClF;AAEA,uBAAiB;AAAA,QACf,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,WAAW;AAAA,QACX,SAAS,OAAO;AAAA,QAChB,WAAW,OAAO;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT;AAEA,YAAQ,KAAK,OAAO;AAAA,MAClB,KAAK;AACH;AAAA,MACF,KAAK;AACH,sBAAc;AACd;AAAA,MACF,KAAK;AACH,cAAM,UAAU,uCAAuC;AAAA,MACzD,KAAK;AACH,cAAM,UAAU,+DAA+D;AAAA,MACjF;AACE,cAAM,IAAI;AAAA,UACR;AAAA,UACA,8BAA8B,KAAK,SAAS,QAAQ,aAAa,MAAM,EAAE;AAAA,UACzE,WAAW;AAAA,QACb;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,UAAU,+DAA+D;AACjF;;;ACpJA,IAAM,uBAAuB;AAoBtB,SAAS,YAAY,OAA6B;AACvD,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,gBAAgB,KAAK,OAAO,GAAG;AACjC,QAAI;AACJ,QAAI;AACF,YAAM,IAAI,IAAI,OAAO;AAAA,IACvB,QAAQ;AACN,YAAM,IAAI,SAAS,oBAAoB,2BAA2B,OAAO,IAAI,WAAW,gBAAgB;AAAA,IAC1G;AACA,UAAM,OAAO,IAAI,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK;AAC9D,UAAM,OAAO,KAAK,QAAQ,SAAS,EAAE;AACrC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF;AACA,WAAO,EAAE,MAAM,QAAQ,IAAI,OAAO;AAAA,EACpC;AACA,SAAO,EAAE,MAAM,QAAQ,QAAQ,SAAS,EAAE,EAAE;AAC9C;AAUA,SAASC,kBAAiB,OAAoD;AAC5E,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,WAAO,KAAK,MAAM,OAAO,KAAK,MAAM,CAAC,GAAG,WAAW,EAAE,SAAS,OAAO,CAAC;AAAA,EACxE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,gBAAgB,SAAyD;AAC7F,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,EAAE,KAAK,IAAI,YAAY,QAAQ,MAAM;AAC3C,QAAM,OAAO,QAAQ,OAAO,QAAQ,OAAO,EAAE;AAE7C,QAAM,WAAW,GAAG,IAAI;AACxB,WAAS,yBAAyB,EAAE,KAAK,SAAS,CAAC;AACnD,QAAM,WAAW,MAAM,QAAQ,UAAU;AAAA,IACvC,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,IAC/D,MAAM,IAAI,gBAAgB;AAAA,MACxB,YAAY;AAAA,MACZ,uBAAuB;AAAA,IACzB,CAAC,EAAE,SAAS;AAAA,EACd,CAAC;AAED,QAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,WAAS,0BAA0B,EAAE,QAAQ,SAAS,QAAQ,OAAO,KAAK,MAAM,CAAC;AAEjF,MAAI,CAAC,SAAS,MAAM,OAAO,KAAK,iBAAiB,UAAU;AAGzD,UAAM,cACJ,OAAO,KAAK,sBAAsB,WAC9B,KAAK,oBACL,kCAAkC,SAAS,MAAM;AACvD,UAAM,IAAI,SAAS,gBAAgB,aAAa,WAAW,UAAU;AAAA,EACvE;AAEA,QAAM,QAAQ,KAAK;AACnB,QAAM,SAASA,kBAAiB,KAAK;AACrC,QAAM,SAA4B;AAAA,IAChC;AAAA,IACA,QAAQ,OAAO,QAAQ,YAAY,WAAW,OAAO,UAAU;AAAA,IAC/D,SAAS,OAAO,QAAQ,aAAa,WAAW,OAAO,WAAW;AAAA,IAClE,WAAW,OAAO,QAAQ,QAAQ,WAAW,IAAI,KAAK,OAAO,MAAM,GAAI,EAAE,YAAY,IAAI;AAAA,EAC3F;AAIA,mBAAiB;AAAA,IACf,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,IACf,WAAW;AAAA,IACX,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,EACpB,CAAC;AAED,SAAO;AACT;;;AFrGO,IAAM,eAAe,IAAIC,SAAQ,OAAO,EAC5C,YAAY,2EAA2E,EACvF,OAAO,0BAA0B,sFAA4E,EAC7G,OAAO,wBAAwB,8CAA8C,WAAW,EACxF,OAAO,aAAa,uDAAuD,EAC3E,OAAO,UAAU,gBAAgB,EACjC,OAAO,mBAAmB,iDAAiD,EAC3E,OAAO,qBAAqB,mDAAmD,EAC/E;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,OAAO,SAAS;AACtB,QAAM,OAAO,iBAAiB,IAAI;AAClC,aAAW,KAAK,OAAO;AAEvB,MAAI,KAAK,QAAQ;AAGf,UAAM,eAAe,YAAY,KAAK,MAAM,EAAE;AAC9C,UAAMC,UAAS,KAAK,SAAS,cAAc,KAAK,MAAM,IAAK,gBAAgB,cAAc;AAEzF,QAAI;AACF,YAAM,SAAS,MAAM,gBAAgB,EAAE,QAAAA,SAAQ,QAAQ,KAAK,OAAO,CAAC;AACpE,YAAM,YAAY,KAAK,iBAAiB,eAAeA,SAAQ,OAAO,KAAK,IAAI;AAE/E,UAAI,SAAS,UAAU;AACrB,qBAAa,YAAY;AACzB,sBAAc,eAAe,mBAAmB,CAAC;AACjD,YAAI,OAAO,QAAS,eAAc,SAAS,OAAO,OAAO;AACzD,YAAI,OAAO,OAAQ,eAAc,WAAW,OAAO,MAAM;AACzD,YAAI,OAAO,UAAW,eAAc,iBAAiB,OAAO,SAAS;AACrE,kBAAU,mGAA8F;AACxG,YAAI,WAAW;AACb,kBAAQ,IAAI;AACZ,oBAAU,4EAAuE;AACjF,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;AAAA,QAChD;AAAA,MACF,OAAO;AACL,qBAAa,MAAM;AAAA,UACjB,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,KAAK;AAAA,UACL,WAAW;AAAA,UACX,SAAS,OAAO;AAAA,UAChB,QAAQ,OAAO;AAAA,UACf,WAAW,OAAO;AAAA,UAClB,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,QACnC,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,UAAU;AAC3B,YAAI,SAAS,UAAU;AACrB,qBAAW,IAAI,OAAO;AAAA,QACxB,OAAO;AACL,sBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,QAC5D;AACA,gBAAQ,KAAK,IAAI,QAAQ;AAAA,MAC3B;AACA,YAAM;AAAA,IACR;AACA;AAAA,EACF;AAEA,QAAM,SAAS,cAAc,KAAK,MAAM;AAExC,MAAI;AACF,UAAM,SAAS,MAAM,oBAAoB;AAAA,MACvC;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,gBAAgB,CAAC,SAAS;AACxB,YAAI,SAAS,UAAU;AACrB,kBAAQ,IAAI;AACZ,oBAAU,6DAA6D;AACvE,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,OAAOC,OAAM,KAAK,UAAU,KAAK,eAAe,CAAC,EAAE;AAC/D,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,OAAOA,OAAM,KAAK,MAAM,KAAK,QAAQ,CAAC,EAAE;AACpD,kBAAQ,IAAI;AACZ,oBAAU,+CAA0C,KAAK,MAAM,KAAK,mBAAmB,EAAE,CAAC,WAAW;AAAA,QACvG,OAAO;AAIL,kBAAQ,OAAO;AAAA,YACb,KAAK,UAAU;AAAA,cACb,OAAO;AAAA,cACP,iBAAiB,KAAK;AAAA,cACtB,yBAAyB,KAAK;AAAA,cAC9B,UAAU,KAAK;AAAA,cACf,WAAW,KAAK;AAAA,YAClB,CAAC,IAAI;AAAA,UACP;AAAA,QACF;AAKA,YAAI,SAAS,YAAY,KAAK,MAAM;AAClC,eAAK,KAAK,uBAAuB,EAAE,MAAM,MAAM;AAAA,UAAC,CAAC;AAAA,QACnD;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,YAAY,KAAK,iBAAiB,eAAe,QAAQ,OAAO,KAAK,IAAI;AAE/E,QAAI,SAAS,UAAU;AACrB,mBAAa,YAAY;AACzB,oBAAc,eAAe,mBAAmB,CAAC;AACjD,UAAI,OAAO,QAAS,eAAc,SAAS,OAAO,OAAO;AACzD,UAAI,OAAO,OAAQ,eAAc,WAAW,OAAO,MAAM;AACzD,UAAI,OAAO,UAAW,eAAc,iBAAiB,OAAO,SAAS;AACrE,gBAAU,oGAA+F;AACzG,UAAI,WAAW;AACb,gBAAQ,IAAI;AACZ,kBAAU,mFAA8E;AACxF,gBAAQ,IAAI;AACZ,gBAAQ,IAAI,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;AAAA,MAChD;AAAA,IACF,OAAO;AACL,mBAAa,MAAM;AAAA,QACjB,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,SAAS,OAAO;AAAA,QAChB,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,QAClB,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACnC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAe,UAAU;AAC3B,UAAI,SAAS,UAAU;AACrB,mBAAW,IAAI,OAAO;AAAA,MACxB,OAAO;AACL,oBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,UAAM;AAAA,EACR;AACF,CAAC;AAQI,SAAS,eAAe,QAAgB,OAAe;AAC5D,SAAO;AAAA,IACL,YAAY;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,KAAK,GAAG,OAAO,QAAQ,OAAO,EAAE,CAAC;AAAA,QACjC,SAAS,EAAE,eAAe,UAAU,KAAK,GAAG;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;;;AD3KO,IAAM,mBAAmB,IAAIC,SAAQ,YAAY,EACrD,YAAY,6EAA6E,EACzF,OAAO,UAAU,gBAAgB,EACjC,OAAO,mBAAmB,iDAAiD,EAC3E,OAAO,OAAO,SAAS;AACtB,QAAM,OAAO,iBAAiB,IAAI;AAElC,MAAI;AAGF,UAAM,OAAO,YAAY;AACzB,UAAM,QAAQ,gBAAgB;AAC9B,UAAM,YAAY,KAAK,WAAW,QAAQ,SAAY,OAAO;AAE7D,UAAM,YAAY,eAAe,cAAc,KAAK,MAAM,GAAG,KAAK,KAAK;AAEvE,QAAI,SAAS,UAAU;AACrB,gBAAU,oEAAoE;AAC9E,cAAQ,IAAI;AACZ,cAAQ,IAAI,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;AAC9C,cAAQ,IAAI;AACZ,UAAI,WAAW;AACb,kBAAU,iBAAiB,SAAS,mEAA8D;AAAA,MACpG;AAAA,IACF,OAAO;AACL,mBAAa,MAAM;AAAA,QACjB,SAAS;AAAA,QACT;AAAA,QACA,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,QACjC,GAAI,OAAO,WAAW,KAAK,WAAW,QAAQ,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,MAC9E,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAe,UAAU;AAC3B,UAAI,SAAS,UAAU;AACrB,gBAAQ,MAAM,IAAI,OAAO;AAAA,MAC3B,OAAO;AACL,oBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,UAAM;AAAA,EACR;AACF,CAAC;;;AI1DH,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAOlB,IAAMC,mBAAkB;AAEjB,IAAM,cAAc,IAAIC,SAAQ,MAAM,EAC1C,YAAY,uBAAuB,EACnC,OAAO,mBAAmB,uBAAuB,EACjD,OAAO,yBAAyB,mCAAmC,EACnE,OAAO,sBAAsB,iCAAiC,EAC9D,OAAO,YAAY,0BAA0B,EAC7C,OAAO,YAAY,qDAAqD,EACxE,OAAO,UAAU,gBAAgB,EACjC,OAAO,mBAAmB,gBAAgBD,gBAAe,EACzD,OAAO,OAAO,SAAS;AACtB,QAAM,OAAO,iBAAiB,IAAI;AAElC,MAAI;AACF,QAAI,KAAK,SAAS,KAAK,YAAY;AACjC,YAAM,SAAiC,CAAC;AAExC,UAAI,KAAK,OAAO;AACd,eAAO,QAAQ,KAAK;AACpB,eAAO,SAAS,KAAK,UAAU,qBAAqB,KAAK,KAAK,KAAK;AAAA,MACrE;AACA,UAAI,KAAK,YAAY;AACnB,eAAO,aAAa,KAAK;AAAA,MAC3B;AAEA,uBAAiB,MAAM;AAEvB,UAAI,SAAS,UAAU;AACrB,qBAAa,0BAA0B,mBAAmB,CAAC;AAC3D,YAAI,KAAK,OAAO;AACd,wBAAc,eAAe,OAAO;AACpC,cAAI,OAAO,OAAQ,eAAc,WAAW,OAAO,MAAM;AAAA,QAC3D;AACA,YAAI,KAAK,YAAY;AACnB,wBAAc,eAAe,OAAO;AAAA,QACtC;AAAA,MACF,OAAO;AACL,qBAAa,MAAM;AAAA,UACjB,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,MAAM,mBAAmB;AAAA,UACzB,GAAI,KAAK,QAAQ,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,UAC9C,GAAI,KAAK,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,QAChD,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ;AACf,YAAM,UAAU,aAAa;AAC7B,UAAI,SAAS,UAAU;AACrB,YAAI,SAAS;AACX,uBAAa,qBAAqB;AAAA,QACpC,OAAO;AACL,oBAAU,6BAA6B;AAAA,QACzC;AAAA,MACF,OAAO;AACL,qBAAa,MAAM,EAAE,SAAS,MAAM,QAAQ,cAAc,gBAAgB,QAAQ,CAAC;AAAA,MACrF;AACA;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ;AACf,UAAI;AACF,cAAM,OAAO,YAAY;AACzB,cAAM,QAAQ,gBAAgB;AAC9B,cAAM,aAAa,KAAK,WAAW,QAAQ,4BAA4B,mBAAmB;AAC1F,cAAM,WAAW,CAAC,EAAE,QAAQ,IAAI,eAAe,OAAO;AACtD,YAAI,SAAS,UAAU;AACrB,uBAAa,kBAAkB;AAC/B,wBAAc,UAAU,UAAU;AAClC,wBAAc,eAAe,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,KAAK,MAAM,MAAM,EAAE,CAAC;AACnF,wBAAc,cAAc,KAAK,cAAc,UAAU,8BAA8B,cAAc;AACrG,cAAI,OAAO,cAAc,WAAW,MAAM,UAAW,eAAc,WAAW,MAAM,SAAS;AAC7F,cAAI,KAAK,OAAQ,eAAc,WAAW,KAAK,MAAM;AACrD,wBAAc,eAAe,WAAW,eAAe,kCAAkC;AAAA,QAC3F,OAAO;AACL,uBAAa,MAAM;AAAA,YACjB,SAAS;AAAA,YACT,QAAQ,KAAK;AAAA,YACb,WAAW,KAAK,aAAa;AAAA,YAC7B,cAAc,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,KAAK,MAAM,MAAM,EAAE;AAAA,YACnE,QAAQ,KAAK;AAAA,YACb,WAAW,OAAO,cAAc,UAAU,MAAM,YAAY;AAAA,YAC5D,YAAY;AAAA,UACd,CAAC;AAAA,QACH;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,eAAe,UAAU;AAC3B,cAAI,SAAS,UAAU;AACrB,uBAAW,IAAI,OAAO;AAAA,UACxB,OAAO;AACL,wBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,UAC5D;AAAA,QACF,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AACA;AAAA,IACF;AAGA,QAAI,SAAS,UAAU;AACrB,cAAQ,IAAI;AACZ,gBAAU,gBAAgB;AAC1B,cAAQ,IAAI,KAAKE,OAAM,KAAK,aAAa,CAAC,wEAAmE;AAC7G,cAAQ,IAAI,KAAKA,OAAM,KAAK,cAAc,CAAC,0CAA0C;AACrF,cAAQ,IAAI,KAAKA,OAAM,KAAK,qBAAqB,CAAC,+BAA+B;AACjF,cAAQ,IAAI,KAAKA,OAAM,KAAK,8BAA8B,CAAC,8CAA8C;AACzG,cAAQ,IAAI;AACZ,cAAQ,IAAI,kBAAkBA,OAAM,KAAK,UAAU,uBAAuB,CAAC,sCAAsC;AACjH,cAAQ,IAAI;AAAA,IACd,OAAO;AACL,mBAAa,MAAM;AAAA,QACjB,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,eAAe,UAAU;AAC3B,UAAI,SAAS,UAAU;AACrB,mBAAW,IAAI,OAAO;AAAA,MACxB,OAAO;AACL,oBAAY,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,IAAI,QAAQ;AAAA,IAC3B;AACA,UAAM;AAAA,EACR;AACF,CAAC;;;AC1IH,SAAS,WAAAC,gBAAe;AAWjB,IAAM,gBAAgB,IAAIC,SAAQ,QAAQ,EAC9C,YAAY,uEAAuE,EACnF,OAAO,UAAU,gBAAgB,EACjC,OAAO,CAAC,SAAS;AAChB,QAAM,OAAO,iBAAiB,IAAI;AAClC,QAAM,iBAAiB,aAAa;AAEpC,MAAI,SAAS,UAAU;AACrB,QAAI,gBAAgB;AAClB,mBAAa,oDAA+C,mBAAmB,CAAC;AAAA,IAClF,OAAO;AACL,gBAAU,6BAA6B;AAAA,IACzC;AAAA,EACF,OAAO;AACL,iBAAa,MAAM,EAAE,SAAS,MAAM,QAAQ,cAAc,eAAe,CAAC;AAAA,EAC5E;AACF,CAAC;;;AC3BH,SAAS,WAAAC,gBAAe;AA4BjB,IAAM,gBAAgB,IAAIC,SAAQ,QAAQ,EAAE;AAAA,EACjD,gCAAgC,WAAW,EAAE,KAAK,IAAI,CAAC;AACzD;AAEA,cACG,QAAQ,mBAAmB,EAC3B,YAAY,oBAAoB,EAChC,OAAO,UAAU,gBAAgB,EACjC,OAAO,CAAC,KAAa,OAAe,SAAS;AAC5C,QAAM,OAAO,iBAAiB,IAAI;AAClC,YAAU,GAAG;AACb,MAAI,QAAQ,UAAW,WAAU,KAAK;AACtC,YAAU,KAAK,KAAK;AAEpB,MAAI,SAAS,SAAU,cAAa,OAAO,GAAG,MAAM,KAAK,EAAE;AAAA,MACtD,cAAa,MAAM,EAAE,SAAS,MAAM,QAAQ,cAAc,KAAK,MAAM,CAAC;AAC7E,CAAC;AAEH,cACG,QAAQ,WAAW,EACnB,YAAY,sBAAsB,EAClC,OAAO,UAAU,gBAAgB,EACjC,OAAO,CAAC,KAAa,SAAS;AAC7B,QAAM,OAAO,iBAAiB,IAAI;AAClC,YAAU,GAAG;AACb,QAAM,QAAQ,WAAW,EAAE,YAAY,GAAG,CAAC;AAE3C,MAAI,SAAS,UAAU;AACrB,QAAI,MAAO,SAAQ,IAAI,KAAK;AAAA,QACvB,WAAU,GAAG,GAAG,aAAa;AAAA,EACpC,OAAO;AACL,iBAAa,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,SAAS,KAAK,CAAC;AAAA,EACjE;AACF,CAAC;AAEH,cACG,QAAQ,MAAM,EACd,MAAM,IAAI,EACV,YAAY,4DAA4D,EACxE,OAAO,UAAU,gBAAgB,EACjC,OAAO,CAAC,SAAS;AAChB,QAAM,OAAO,iBAAiB,IAAI;AAClC,QAAM,SAAS,WAAW;AAC1B,QAAM,iBAAiB,cAAc;AAErC,MAAI,SAAS,UAAU;AACrB,cAAU,aAAa,cAAc,CAAC;AACtC,kBAAc,WAAW,OAAO,UAAU,aAAa,eAAe,EAAE;AACxE,QAAI,QAAQ,IAAI,eAAe;AAC7B,gBAAU,mEAA8D,cAAc,GAAG;AAAA,IAC3F;AAAA,EACF,OAAO;AACL,iBAAa,MAAM;AAAA,MACjB,SAAS;AAAA,MACT,MAAM,cAAc;AAAA,MACpB;AAAA,MACA,UAAU,EAAE,QAAQ,eAAe;AAAA,IACrC,CAAC;AAAA,EACH;AACF,CAAC;AAEH,cACG,QAAQ,aAAa,EACrB,YAAY,uBAAuB,EACnC,OAAO,UAAU,gBAAgB,EACjC,OAAO,CAAC,KAAa,SAAS;AAC7B,QAAM,OAAO,iBAAiB,IAAI;AAClC,YAAU,GAAG;AACb,QAAM,UAAU,YAAY,GAAG;AAE/B,MAAI,SAAS,UAAU;AACrB,QAAI,QAAS,cAAa,SAAS,GAAG,EAAE;AAAA,QACnC,WAAU,GAAG,GAAG,cAAc;AAAA,EACrC,OAAO;AACL,iBAAa,MAAM,EAAE,SAAS,MAAM,QAAQ,gBAAgB,KAAK,QAAQ,CAAC;AAAA,EAC5E;AACF,CAAC;AAEH,SAAS,UAAU,KAAuC;AACxD,MAAI,CAAC,YAAY,GAAG,GAAG;AACrB,UAAM,gBAAgB,uBAAuB,GAAG,kBAAkB,WAAW,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EAC7F;AACF;AAEA,SAAS,UAAU,OAAqB;AACtC,MAAI;AACF,QAAI,IAAI,KAAK;AAAA,EACf,QAAQ;AACN,UAAM,gBAAgB,IAAI,KAAK,sBAAsB;AAAA,EACvD;AACF;;;AzBtGA,IAAM,UAAU,IAAIC,UAAQ,EACzB,KAAK,OAAO,EACZ;AAAA,EACC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCF,EACC,QAAQ,SAAS,eAAe;AAEnC,QAAQ,WAAW,YAAY;AAC/B,QAAQ,WAAW,aAAa;AAChC,QAAQ,WAAW,aAAa;AAChC,QAAQ,WAAW,cAAc;AACjC,QAAQ,WAAW,cAAc;AACjC,QAAQ,WAAW,kBAAkB;AACrC,QAAQ,WAAW,gBAAgB;AACnC,QAAQ,WAAW,aAAa;AAChC,QAAQ,WAAW,WAAW;AAE9B,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,CAAC,QAAQ;AAC9C,MAAI,eAAe,UAAU;AAC3B,QAAI,QAAQ,OAAO,OAAO;AACxB,cAAQ,MAAM,IAAI,OAAO;AAAA,IAC3B,OAAO;AACL,cAAQ,OAAO;AAAA,QACb,KAAK,UAAU;AAAA,UACb,SAAS;AAAA,UACT,OAAO,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ;AAAA,QAChD,CAAC,IAAI;AAAA,MACP;AAAA,IACF;AACA,YAAQ,KAAK,IAAI,QAAQ;AAAA,EAC3B;AAEA,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,CAAC;AAChB,CAAC;","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/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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@animaapp/cli",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
4
4
  "description": "Generate production-ready apps from prompts, URLs, or Figma designs",
5
5
  "type": "module",
6
6
  "bin": {