@vocoder/cli 0.13.1 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.mjs +3 -8
- package/dist/bin.mjs.map +1 -1
- package/package.json +3 -3
package/dist/bin.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bin.ts","../src/commands/init.ts","../src/utils/write-config.ts","../src/utils/github-connect.ts","../src/utils/local-server.ts","../src/utils/project-create.ts","../src/utils/branch-select.ts","../src/utils/theme.ts","../src/utils/locale-search.ts","../src/utils/git-identity.ts","../src/utils/workspace.ts","../src/commands/locales.ts","../src/commands/sync.ts","../src/utils/branch.ts","../src/utils/config.ts","../src/commands/logout.ts","../src/commands/app-config.ts","../src/commands/translations.ts","../src/commands/create-app.ts","../src/commands/whoami.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { init } from \"./commands/init.js\";\nimport {\n\taddLocales,\n\tlistProjectLocales,\n\tlistSupportedLocales,\n\tremoveLocales,\n} from \"./commands/locales.js\";\nimport { logout } from \"./commands/logout.js\";\nimport { appConfig } from \"./commands/app-config.js\";\nimport { sync } from \"./commands/sync.js\";\nimport { getTranslations } from \"./commands/translations.js\";\nimport { createApp } from \"./commands/create-app.js\";\nimport { whoami } from \"./commands/whoami.js\";\n\n/**\n * Collector function for repeated CLI options\n * Allows multiple --include or --exclude flags\n */\nfunction collect(value: string, previous: string[] = []): string[] {\n\treturn previous.concat([value]);\n}\n\nasync function runCommand(\n\tcommand: (options: any) => Promise<number>,\n\toptions: any,\n): Promise<void> {\n\tconst exitCode = await command(options);\n\t// Force exit so open stdin handles from readline/clack don't stall the process.\n\tprocess.exit(exitCode);\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"vocoder\")\n\t.description(\"Vocoder CLI - Project setup and string extraction\")\n\t.version(\"0.1.5\");\n\nprogram\n\t.command(\"init\")\n\t.description(\"Authenticate and provision Vocoder for this project\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.option(\"--yes\", \"Allow overwriting existing local config values\")\n\t.option(\n\t\t\"--ci\",\n\t\t\"Non-interactive mode: print auth URL to stdout, skip browser open\",\n\t)\n\t.option(\"--app-name <name>\", \"Starter app name to create\")\n\t.option(\"--source-locale <locale>\", \"Source locale for the starter project\")\n\t.option(\n\t\t\"--target-locales <list>\",\n\t\t\"Comma-separated target locales (e.g. es,fr,de)\",\n\t)\n\t.action((options) => runCommand(init, options));\n\nprogram\n\t.command(\"sync\")\n\t.description(\"Extract strings and sync translations\")\n\t.option(\"--branch <branch>\", \"Override detected branch\")\n\t.option(\"--mode <mode>\", \"Sync mode: auto, required, best-effort\", \"auto\")\n\t.option(\"--max-wait <ms>\", \"Max wait for translations (ms)\")\n\t.option(\"--force\", \"Force re-extraction even if no changes\")\n\t.option(\"--dry-run\", \"Preview without syncing\")\n\t.option(\"--no-fallback\", \"Disable fallback to cached translations\")\n\t.option(\"--include <pattern>\", \"Include glob pattern\", collect, [])\n\t.option(\"--exclude <pattern>\", \"Exclude glob pattern\", collect, [])\n\t.option(\"--verbose\", \"Detailed output\")\n\t.action((options) => {\n\t\tconst translated: Record<string, unknown> = { ...options };\n\t\tif (options.maxWait) translated.maxWaitMs = Number(options.maxWait);\n\t\tif (options.fallback === false) translated.noFallback = true;\n\t\treturn runCommand(sync, translated);\n\t});\n\nprogram\n\t.command(\"logout\")\n\t.description(\"Log out and remove stored credentials\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(logout, options));\n\nprogram\n\t.command(\"whoami\")\n\t.description(\"Show the currently authenticated user\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(whoami, options));\n\n// ── Project management ────────────────────────────────────────────────────────\n\nconst localesCmd = program\n\t.command(\"locales\")\n\t.description(\"Manage project target locales\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(listProjectLocales, options));\n\nlocalesCmd\n\t.command(\"add <codes...>\")\n\t.description(\"Add one or more target locales by BCP 47 code (e.g. fr de pt-BR)\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((codes: string[], options) =>\n\t\trunCommand((opts) => addLocales(codes, opts), options),\n\t);\n\nlocalesCmd\n\t.command(\"remove <codes...>\")\n\t.description(\"Remove one or more target locales by BCP 47 code\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((codes: string[], options) =>\n\t\trunCommand((opts) => removeLocales(codes, opts), options),\n\t);\n\nlocalesCmd\n\t.command(\"supported\")\n\t.description(\"List all locales supported by Vocoder\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(listSupportedLocales, options));\n\nprogram\n\t.command(\"project\")\n\t.description(\"Show current app configuration\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(appConfig, options));\n\nprogram\n\t.command(\"translations\")\n\t.description(\"Download the current translation snapshot\")\n\t.option(\"--branch <branch>\", \"Git branch (auto-detected if omitted)\")\n\t.option(\"--locale <locale>\", \"Fetch a specific locale only\")\n\t.option(\"--output <dir>\", \"Write locale JSON files to this directory\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(getTranslations, options));\n\nprogram\n\t.command(\"create-app\")\n\t.description(\"Create a new Vocoder app (requires prior `vocoder init`)\")\n\t.requiredOption(\"--name <name>\", \"App display name\")\n\t.requiredOption(\"--source-locale <code>\", \"Source language BCP 47 code (e.g. en)\")\n\t.requiredOption(\"--workspace <org-id>\", \"Workspace organization ID\")\n\t.option(\n\t\t\"--target-locales <codes>\",\n\t\t\"Comma-separated target locale codes (e.g. fr,de,pt-BR)\",\n\t)\n\t.option(\n\t\t\"--target-branches <branches>\",\n\t\t\"Comma-separated branch names to sync (default: main)\",\n\t)\n\t.option(\n\t\t\"--repo <canonical>\",\n\t\t\"Git repo canonical (e.g. github:owner/repo). Auto-detected from git remote if omitted.\",\n\t)\n\t.option(\n\t\t\"--app-dir <path>\",\n\t\t\"App directory within the repo for monorepos (default: .)\",\n\t)\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => {\n\t\tconst translated = {\n\t\t\t...options,\n\t\t\t// Commander camelCases dashed options\n\t\t\tsourceLocale: options.sourceLocale,\n\t\t\ttargetLocales: options.targetLocales,\n\t\t\ttargetBranches: options.targetBranches,\n\t\t\tworkspace: options.workspace,\n\t\t};\n\t\treturn runCommand(createApp, translated);\n\t});\n\nprogram.parse(process.argv);\n","import * as p from \"@clack/prompts\";\n\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport {\n\tbuildInstallCommand,\n\tdetectLocalEcosystem,\n\tgetPackagesToInstall,\n} from \"../utils/detect-local.js\";\nimport {\n\tclearAuthData,\n\treadAuthData,\n\twriteAuthData,\n\tverifyStoredAuth,\n} from \"../utils/auth-store.js\";\nimport { execSync, spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { findExistingConfig, writeVocoderConfig } from \"../utils/write-config.js\";\nimport {\n\trunGitHubDiscoveryFlow,\n\trunGitHubInstallFlow,\n\tselectGitHubInstallation,\n} from \"../utils/github-connect.js\";\nimport {\n\trunAppCreate,\n\trunProjectCreate,\n} from \"../utils/project-create.js\";\n\nimport type { InitOptions } from \"../types.js\";\nimport chalk from \"chalk\";\nimport { highlight, info } from \"../utils/theme.js\";\nimport { getSetupSnippets } from \"../utils/setup-snippets.js\";\nimport { join } from \"node:path\";\nimport { config as loadEnv } from \"dotenv\";\nimport { resolveGitContext } from \"../utils/git-identity.js\";\nimport { selectWorkspace } from \"../utils/workspace.js\";\nimport { startCallbackServer } from \"../utils/local-server.js\";\n\nloadEnv();\n\nconst SUBSCRIPTION_SETTINGS_PATH =\n\t\"/dashboard/workspace/settings?tab=subscription\";\n\nasync function sleep(ms: number): Promise<void> {\n\tawait new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n\tif (!process.stdout.isTTY || process.env.CI === \"true\") {\n\t\treturn false;\n\t}\n\n\tlet command: string;\n\tlet args: string[];\n\n\tif (process.platform === \"darwin\") {\n\t\tcommand = \"open\";\n\t\targs = [url];\n\t} else if (process.platform === \"win32\") {\n\t\tcommand = \"rundll32\";\n\t\targs = [\"url.dll,FileProtocolHandler\", url];\n\t} else {\n\t\tcommand = \"xdg-open\";\n\t\targs = [url];\n\t}\n\n\treturn await new Promise<boolean>((resolve) => {\n\t\ttry {\n\t\t\tconst child = spawn(command, args, {\n\t\t\t\tdetached: true,\n\t\t\t\tstdio: \"ignore\",\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\n\t\t\tlet settled = false;\n\t\t\tchild.once(\"spawn\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tchild.unref();\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t\tchild.once(\"error\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t});\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t}, 300);\n\t\t} catch {\n\t\t\tresolve(false);\n\t\t}\n\t});\n}\n\nfunction isPlanLimitFailure(message?: string): boolean {\n\tif (!message) return false;\n\treturn /limit|upgrade/i.test(message);\n}\n\nfunction getSubscriptionSettingsUrl(apiUrl: string): string {\n\treturn new URL(SUBSCRIPTION_SETTINGS_PATH, apiUrl).toString();\n}\n\nfunction printPlanLimitMessage(apiUrl: string, message: string): void {\n\tp.log.error(`You are over your plan limits.\\n ${message}`);\n\tp.log.info(`Manage subscription: ${getSubscriptionSettingsUrl(apiUrl)}`);\n}\n\ninterface ScaffoldParams {\n\tsourceLocale: string;\n\ttargetBranches: string[];\n\tappDir?: string;\n}\n\nfunction runScaffold(params: ScaffoldParams): void {\n\tconst { sourceLocale, targetBranches, appDir } = params;\n\n\tconst detection = detectLocalEcosystem();\n\tconst useTypeScript = detection.isTypeScript;\n\n\tif (detection.ecosystem) {\n\t\tconst frameworkLabel = detection.framework ?? detection.ecosystem;\n\t\tconst pmLabel = detection.packageManager;\n\t\tp.log.info(`Detected: ${chalk.bold(frameworkLabel)} (${pmLabel})`);\n\t}\n\n\tconst { devPackages, runtimePackages } = getPackagesToInstall(detection);\n\tconst allPackages = [...devPackages, ...runtimePackages];\n\tif (allPackages.length > 0) {\n\t\tp.log.info(\"\");\n\t\tconst installSpinner = p.spinner();\n\t\tinstallSpinner.start(`Installing ${allPackages.join(\", \")}...`);\n\n\t\ttry {\n\t\t\tif (devPackages.length > 0) {\n\t\t\t\texecSync(\n\t\t\t\t\tbuildInstallCommand(detection.packageManager, devPackages, true),\n\t\t\t\t\t{ stdio: \"pipe\", cwd: process.cwd() },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (runtimePackages.length > 0) {\n\t\t\t\texecSync(\n\t\t\t\t\tbuildInstallCommand(detection.packageManager, runtimePackages, false),\n\t\t\t\t\t{ stdio: \"pipe\", cwd: process.cwd() },\n\t\t\t\t);\n\t\t\t}\n\t\t\tinstallSpinner.stop(`Installed ${allPackages.join(\", \")}`);\n\t\t} catch {\n\t\t\tinstallSpinner.stop(\"Package installation failed\");\n\t\t\tconst cmds = [\n\t\t\t\tdevPackages.length > 0\n\t\t\t\t\t? buildInstallCommand(detection.packageManager, devPackages, true)\n\t\t\t\t\t: null,\n\t\t\t\truntimePackages.length > 0\n\t\t\t\t\t? buildInstallCommand(detection.packageManager, runtimePackages, false)\n\t\t\t\t\t: null,\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\" && \");\n\t\t\tp.log.warn(`Run manually: ${highlight(cmds)}`);\n\t\t}\n\t} else if (detection.ecosystem) {\n\t\tp.log.info(`Packages: ${chalk.green(\"already installed\")}`);\n\t}\n\n\tconst snippets = getSetupSnippets({\n\t\tframework: detection.framework,\n\t\tecosystem: detection.ecosystem,\n\t\tsourceLocale,\n\t\ttargetBranches,\n\t\tappDir,\n\t});\n\n\tconst steps: Array<{ label: string; hint: string; code: string }> = [];\n\n\tif (snippets.pluginStep) {\n\t\tsteps.push({\n\t\t\tlabel: snippets.pluginStep.file,\n\t\t\thint: \"register the build plugin so Vocoder can extract your strings\",\n\t\t\tcode: snippets.pluginStep.code,\n\t\t});\n\t}\n\n\tif (snippets.providerStep) {\n\t\tsteps.push({\n\t\t\tlabel: snippets.providerStep.file,\n\t\t\thint: \"wrap your app so translations load at runtime\",\n\t\t\tcode: snippets.providerStep.code,\n\t\t});\n\t}\n\n\tsteps.push({\n\t\tlabel: \"wrap translatable text\",\n\t\thint: \"mark strings for extraction — Vocoder picks these up on push\",\n\t\tcode: snippets.wrapStep.code,\n\t});\n\n\tp.log.message(\"\");\n\tp.log.message(chalk.bold(\"Finish setup in your code\"));\n\tp.log.message(\"\");\n\n\tfor (let i = 0; i < steps.length; i++) {\n\t\tconst step = steps[i]!;\n\t\tp.log.step(\n\t\t\t`${chalk.bold(step.label)} ${chalk.dim(`— ${step.hint}`)}`,\n\t\t);\n\t\tprintCodeBlock(step.code);\n\t\tif (i < steps.length - 1) p.log.message(\"\");\n\t}\n\n\t// Write vocoder.config.{ts,js} if not already present\n\tconst written = writeVocoderConfig({ targetBranches, useTypeScript });\n\tif (written) {\n\t\tp.log.success(`Created ${highlight(written)}`);\n\t} else if (!findExistingConfig(process.cwd())) {\n\t\tconst ext = useTypeScript ? \"ts\" : \"js\";\n\t\tp.log.warn(\n\t\t\t`Could not write vocoder.config.${ext} — create it manually with your extraction patterns.`,\n\t\t);\n\t}\n\n\tp.log.message(\"\");\n\tconst branchList =\n\t\ttargetBranches.length > 0\n\t\t\t? targetBranches.map((b) => highlight(b)).join(\" or \")\n\t\t\t: highlight(\"your target branch\");\n\tp.log.success(\n\t\t`Push to ${branchList} to trigger your first translation run.`,\n\t);\n\tp.log.message(info(\" Docs: https://vocoder.app/docs/getting-started\"));\n}\n\n\nfunction writeApiKeyToEnv(apiKey: string): boolean {\n\tconst envPath = join(process.cwd(), \".env\");\n\tif (!existsSync(envPath)) return false;\n\n\ttry {\n\t\tconst content = readFileSync(envPath, \"utf-8\");\n\t\tconst keyLine = `VOCODER_API_KEY=${apiKey}`;\n\t\tlet updated: string;\n\n\t\tif (/^VOCODER_API_KEY=/m.test(content)) {\n\t\t\tupdated = content.replace(/^VOCODER_API_KEY=.*/m, keyLine);\n\t\t} else {\n\t\t\tconst sep = content.length > 0 && !content.endsWith(\"\\n\") ? \"\\n\" : \"\";\n\t\t\tupdated = `${content}${sep}${keyLine}\\n`;\n\t\t}\n\n\t\twriteFileSync(envPath, updated);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction printApiKey(apiKey: string): void {\n\tconst saved = writeApiKeyToEnv(apiKey);\n\n\tp.log.message(\"\");\n\tp.log.message(chalk.bold(\"Your API Key\"));\n\tprintCodeBlock(`VOCODER_API_KEY=${apiKey}`);\n\tif (saved) {\n\t\tp.log.success(chalk.dim(\"Saved to .env\"));\n\t} else {\n\t\tp.log.message(chalk.dim(\" Add the above to your .env file\"));\n\t}\n}\n\n// TODO: uncomment when @vocoder/mcp is published and functional\n// function printMcpSetup(apiKey: string): void {\n// \tconst addCommand = `claude mcp add --scope project --transport stdio \\\\\\n --env VOCODER_API_KEY=${apiKey} \\\\\\n vocoder -- npx -y @vocoder/mcp`;\n//\n// \tconst teamConfig = JSON.stringify(\n// \t\t{\n// \t\t\tmcpServers: {\n// \t\t\t\tvocoder: {\n// \t\t\t\t\ttype: \"stdio\",\n// \t\t\t\t\tcommand: \"npx\",\n// \t\t\t\t\targs: [\"-y\", \"@vocoder/mcp\"]\n// \t\t\t\t},\n// \t\t\t},\n// \t\t},\n// \t\tnull,\n// \t\t2,\n// \t);\n//\n// \tp.log.message(\"\");\n// \tp.log.message(chalk.bold(\"Use Vocoder with Claude Code\"));\n// \tp.log.message(\"\");\n// \tp.log.message(\"Run once to register the MCP server (embeds your key locally):\");\n// \tprintCodeBlock(addCommand);\n// \tp.log.message(\"\");\n// \tp.log.message(\n// \t\t\"To share with your team, commit \" +\n// \t\t\thighlight(\".mcp.json\") +\n// \t\t\t\" with an env var reference —\",\n// \t);\n// \tp.log.message(\n// \t\t\"each developer sets \" + highlight(\"VOCODER_API_KEY\") + \" in their own .env:\",\n// \t);\n// \tprintCodeBlock(teamConfig);\n// \tp.log.message(\"\");\n// \tp.log.message(chalk.gray(\"Docs: https://vocoder.app/docs/mcp\"));\n// }\n\nfunction printCodeBlock(code: string): void {\n\tconst lines = code.split(\"\\n\");\n\tconst maxLen = lines.reduce(\n\t\t(max: number, line: string) => Math.max(max, line.length),\n\t\t0,\n\t);\n\tconst bar = chalk.gray(\"│\");\n\tconst pad = (s: string) => s + \" \".repeat(maxLen - s.length);\n\n\tprocess.stdout.write(`${chalk.gray(\"│\")}\\n`);\n\tprocess.stdout.write(\n\t\t`${chalk.gray(\"│\")} ${chalk.gray(`┌${\"─\".repeat(maxLen + 2)}┐`)}\\n`,\n\t);\n\tfor (const line of lines) {\n\t\tprocess.stdout.write(`${chalk.gray(\"│\")} ${bar} ${pad(line)} ${bar}\\n`);\n\t}\n\tprocess.stdout.write(\n\t\t`${chalk.gray(\"│\")} ${chalk.gray(`└${\"─\".repeat(maxLen + 2)}┘`)}\\n`,\n\t);\n}\n\n// ── Auth helpers ─────────────────────────────────────────────────────────────\n\n\n\n/**\n * Run the browser authentication flow.\n * Returns `{ token, userInfo, organizationId? }` on success, or null if cancelled.\n * When `organizationId` is set, the GitHub App was installed in the same browser\n * trip — the caller should skip workspace selection and GitHub connect.\n *\n * @param reauth - When true, the user has an expired token and already has a workspace.\n * Use verificationUrl (auth/cli page) instead of installUrl so we don't create a\n * duplicate workspace. The direct-to-GitHub install URL is only for first-time setup.\n */\nasync function runAuthFlow(\n\tapi: VocoderAPI,\n\toptions: InitOptions,\n\treauth = false,\n\trepoCanonical?: string,\n): Promise<{\n\ttoken: string;\n\tuserId: string;\n\temail: string;\n\tname: string | null;\n\torganizationId?: string;\n\tdiscoveryReady?: boolean;\n} | null> {\n\t// Try to start a local callback server for instant token delivery.\n\t// In --ci mode the browser step is handled externally, so skip the callback\n\t// server and go straight to polling — simpler and testable.\n\tlet server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n\tif (!options.ci) {\n\t\ttry {\n\t\t\tserver = await startCallbackServer();\n\t\t} catch {\n\t\t\t// Port conflict or other issue — fall back to polling\n\t\t}\n\t}\n\n\tconst session = await api.startCliAuthSession(server?.port, repoCanonical);\n\t// Re-auth: user already has a workspace — use verificationUrl (auth/cli page)\n\t// so we don't trigger a new GitHub App install and create a duplicate workspace.\n\t// First-time: use installUrl to combine Vocoder auth + App install in one trip.\n\tconst browserUrl = reauth\n\t\t? session.verificationUrl\n\t\t: (session.installUrl ?? session.verificationUrl);\n\tconst expiresAt = new Date(session.expiresAt).getTime();\n\n\tif (options.ci) {\n\t\t// Machine-readable output for automated test harnesses.\n\t\t// Parsed by e2e/helpers/cli.ts: /^VOCODER_AUTH_URL: (.+)$/m\n\t\tprocess.stdout.write(`VOCODER_AUTH_URL: ${browserUrl}\\n`);\n\t\t// Also emit the session ID separately so tests can expire/complete sessions\n\t\tprocess.stdout.write(`VOCODER_SESSION_ID: ${session.sessionId}\\n`);\n\t} else if (\n\t\tprocess.stdin.isTTY &&\n\t\tprocess.stdout.isTTY &&\n\t\tprocess.env.CI !== \"true\"\n\t) {\n\t\tif (reauth) {\n\t\t\t// Re-auth: token expired, just sign in — no install choice needed\n\t\t\tif (!options.yes) {\n\t\t\t\tconst shouldOpen = await p.confirm({\n\t\t\t\t\tmessage: \"Open your browser to sign in again?\",\n\t\t\t\t});\n\t\t\t\tif (p.isCancel(shouldOpen)) {\n\t\t\t\t\tserver?.close();\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tif (!shouldOpen) {\n\t\t\t\t\tserver?.close();\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\tconst opened = await tryOpenBrowser(browserUrl);\n\t\t\t\t\tif (!opened) {\n\t\t\t\t\t\tp.note(browserUrl, \"Sign In\");\n\t\t\t\t\t\tp.log.info(\"Open the URL above manually to continue.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait tryOpenBrowser(browserUrl);\n\t\t\t}\n\t\t} else {\n\t\t\t// First-time setup: let user choose install vs link existing\n\t\t\tlet isLinkFlow = false;\n\t\t\tif (!options.yes) {\n\t\t\t\tconst connectChoice = await p.select<string>({\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"Vocoder needs to be installed on your GitHub account to get started\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"install\",\n\t\t\t\t\t\t\tlabel: \"Install GitHub App\",\n\t\t\t\t\t\t\thint: \"recommended\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ value: \"link\", label: \"Already installed? Link your account\" },\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tif (p.isCancel(connectChoice)) {\n\t\t\t\t\tserver?.close();\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tisLinkFlow = connectChoice === \"link\";\n\t\t\t}\n\n\t\t\t// For \"link\": get the OAuth-only URL from the server (no install page shown)\n\t\t\tlet urlToOpen = browserUrl;\n\t\t\tif (isLinkFlow) {\n\t\t\t\ttry {\n\t\t\t\t\tconst linkSession = await api.startCliGitHubLinkSession(\n\t\t\t\t\t\tsession.sessionId,\n\t\t\t\t\t\tserver?.port,\n\t\t\t\t\t);\n\t\t\t\t\turlToOpen = linkSession.oauthUrl;\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall back to install URL if link-start fails\n\t\t\t\t\turlToOpen = browserUrl;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Open browser immediately — no separate confirm needed\n\t\t\tconst opened = await tryOpenBrowser(urlToOpen);\n\t\t\tif (!opened) {\n\t\t\t\t// Only show URL as a fallback if auto-open fails\n\t\t\t\tp.log.warn(\"Could not open your browser automatically.\");\n\t\t\t\tp.note(urlToOpen, \"GitHub\");\n\t\t\t\tp.log.info(\"Open the URL above to continue.\");\n\t\t\t}\n\t\t}\n\t}\n\n\tconst authSpinner = p.spinner();\n\tauthSpinner.start(\"Waiting for GitHub authorization...\");\n\n\tlet rawToken: string | null = null;\n\tlet callbackOrganizationId: string | undefined;\n\tlet callbackDiscoveryReady = false;\n\n\tif (server) {\n\t\t// Fast path: wait for the localhost callback\n\t\ttry {\n\t\t\tconst deadline = Math.min(expiresAt, Date.now() + 10 * 60 * 1000);\n\t\t\tconst timeoutMs = deadline - Date.now();\n\t\t\tconst params = await Promise.race([\n\t\t\t\tserver.waitForCallback(),\n\t\t\t\tnew Promise<null>((resolve) =>\n\t\t\t\t\tsetTimeout(() => resolve(null), timeoutMs),\n\t\t\t\t),\n\t\t\t]);\n\n\t\t\tif (params && typeof params.token === \"string\") {\n\t\t\t\trawToken = params.token;\n\t\t\t\tif (\n\t\t\t\t\ttypeof params.organizationId === \"string\" &&\n\t\t\t\t\tparams.organizationId\n\t\t\t\t) {\n\t\t\t\t\tcallbackOrganizationId = params.organizationId;\n\t\t\t\t}\n\t\t\t\t// Link flow: callback signals discovery results are cached\n\t\t\t\tif (params.discovery_ready === \"1\") {\n\t\t\t\t\tcallbackDiscoveryReady = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to polling\n\t\t} finally {\n\t\t\tserver.close();\n\t\t}\n\t}\n\n\tif (!rawToken) {\n\t\t// Polling fallback\n\t\twhile (Date.now() < expiresAt) {\n\t\t\tconst result = await api.pollCliAuthSession(session.sessionId);\n\n\t\t\tif (result.status === \"complete\") {\n\t\t\t\trawToken = result.token;\n\t\t\t\tif (result.organizationId) {\n\t\t\t\t\tcallbackOrganizationId = result.organizationId;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (result.status === \"failed\") {\n\t\t\t\tauthSpinner.stop();\n\t\t\t\tp.log.error(result.reason);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Still pending — wait 2s before next poll\n\t\t\tawait sleep(2000);\n\t\t}\n\t}\n\n\tif (!rawToken) {\n\t\tauthSpinner.stop();\n\t\tp.log.error(\"The authentication link expired. Run `vocoder init` again.\");\n\t\treturn null;\n\t}\n\n\t// Validate the token and get user info\n\tconst userInfo = await api.getCliUserInfo(rawToken);\n\tauthSpinner.stop(`Authenticated as ${chalk.bold(userInfo.email)}`);\n\n\treturn {\n\t\ttoken: rawToken,\n\t\t...userInfo,\n\t\torganizationId: callbackOrganizationId,\n\t\tdiscoveryReady: callbackDiscoveryReady,\n\t};\n}\n\n// ── Main command ─────────────────────────────────────────────────────────────\n\nexport async function init(options: InitOptions = {}): Promise<number> {\n\tconst apiUrl =\n\t\toptions.apiUrl || process.env.VOCODER_API_URL || \"https://vocoder.app\";\n\n\tp.intro(chalk.bold(\"Vocoder Setup\"));\n\n\ttry {\n\t\t// ── Detect git context ──────────────────────────────────────────────────\n\t\tconst gitContext = resolveGitContext();\n\t\tconst identity = gitContext.identity;\n\n\t\tif (gitContext.warnings.length > 0) {\n\t\t\tfor (const warning of gitContext.warnings) {\n\t\t\t\tp.log.warn(warning);\n\t\t\t}\n\t\t}\n\n\t\t// ── Fast lookup: does a project already exist for this repo? ────────────\n\t\t// No spinner — this is a fast DB read and we don't want an empty ◇ on miss.\n\t\tlet existingAppsForRepo: Array<{\n\t\t\tappDir: string;\n\t\t\tprojectId: string;\n\t\t\tprojectName: string;\n\t\t\torganizationName: string;\n\t\t}> = [];\n\t\tlet repoProjectId: string | null = null;\n\t\tlet repoProjectName: string | null = null;\n\n\t\tif (identity) {\n\t\t\tconst anonApi = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\t\t\tconst lookup = await anonApi.lookupAppByRepo({\n\t\t\t\trepoCanonical: identity.repoCanonical,\n\t\t\t\tappDir: identity.repoAppDir,\n\t\t\t});\n\n\t\t\t// Exact match: this scope is already configured.\n\t\t\tif (lookup.exactMatch) {\n\t\t\t\tconst { exactMatch } = lookup;\n\t\t\t\tp.log.success(`Project: ${chalk.bold(exactMatch.projectName)}`);\n\t\t\t\tp.log.info(\n\t\t\t\t\t`Branches: ${highlight((exactMatch.targetBranches ?? [\"main\"]).join(\", \"))}`,\n\t\t\t\t);\n\n\t\t\t\tconst needsKey = await p.confirm({\n\t\t\t\t\tmessage: \"Need to regenerate your API key?\",\n\t\t\t\t});\n\n\t\t\t\tif (!p.isCancel(needsKey) && needsKey) {\n\t\t\t\t\t// Auth required — run sign-in flow before generating key\n\t\t\t\t\tconst anonApi = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\t\t\t\t\tconst authResult = await runAuthFlow(\n\t\t\t\t\t\tanonApi,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\t/* reauth */ true,\n\t\t\t\t\t);\n\t\t\t\t\tif (!authResult) return 1;\n\n\t\t\t\t\tconst spinner = p.spinner();\n\t\t\t\t\tspinner.start(\"Generating new API key...\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { apiKey } = await anonApi.regenerateProjectApiKey(\n\t\t\t\t\t\t\tauthResult.token,\n\t\t\t\t\t\t\texactMatch.projectId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tspinner.stop(\"New API key generated\");\n\t\t\t\t\t\tprintApiKey(apiKey);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tspinner.stop(\"Failed to generate key\");\n\t\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tp.log.error(`Could not generate API key: ${msg}`);\n\t\t\t\t\t\tp.log.info(\"Try again or generate one from the dashboard.\");\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst isTs = detectLocalEcosystem().isTypeScript;\n\t\t\t\tconst written = writeVocoderConfig({ targetBranches: exactMatch.targetBranches ?? [\"main\"], useTypeScript: isTs });\n\t\t\t\tif (written) p.log.success(`Created ${highlight(written)}`);\n\t\t\t\tp.outro(\"Vocoder is already set up for this repository.\");\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\t// Whole-repo app exists: covers this repo from any directory — confirm and exit.\n\t\t\tif (lookup.hasWholeRepoApp) {\n\t\t\t\tconst wholeRepo = lookup.existingApps.find((a) => a.appDir === \"\");\n\t\t\t\tif (wholeRepo) {\n\t\t\t\t\tp.log.success(`Project: ${chalk.bold(wholeRepo.projectName)}`);\n\t\t\t\t\tconst isTs = detectLocalEcosystem().isTypeScript;\n\t\t\t\t\tconst written = writeVocoderConfig({ targetBranches: [\"main\"], useTypeScript: isTs });\n\t\t\t\t\tif (written) p.log.success(`Created ${highlight(written)}`);\n\t\t\t\t\tp.outro(\"Vocoder is already set up for this repository.\");\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Other scoped apps exist: this repo has a project but not for this scope.\n\t\t\t// Store for display + validation in the app directory prompt.\n\t\t\tif (lookup.existingApps.length > 0) {\n\t\t\t\texistingAppsForRepo = lookup.existingApps;\n\t\t\t\t// All apps belong to the same project (one project per repo)\n\t\t\t\trepoProjectId = lookup.existingApps[0]?.projectId ?? null;\n\t\t\t\trepoProjectName = lookup.existingApps[0]?.projectName ?? null;\n\t\t\t}\n\t\t}\n\n\t\t// ── Auth: check stored token, prompt if missing ─────────────────────────\n\t\tconst api = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\t\tlet userToken: string;\n\t\tlet userEmail: string;\n\t\tlet userName: string | null;\n\n\t\t// organizationId is set when auth+GitHub install completed in one browser trip\n\t\tlet authOrganizationId: string | undefined;\n\n\t\tconst storedAuth = await verifyStoredAuth(api);\n\n\t\t\tif (storedAuth.status === \"valid\") {\n\t\t\t\tp.log.success(`Authenticated as ${chalk.bold(storedAuth.email)}`);\n\t\t\t\tuserToken = storedAuth.token;\n\t\t\t\tuserEmail = storedAuth.email;\n\t\t\t\tuserName = storedAuth.name;\n\t\t\t} else {\n\t\t\t\t// \"gone\" = user deleted from DB → full first-time flow (installUrl)\n\t\t\t\t// \"expired\" = token rejected → reauth via verificationUrl (no new org)\n\t\t\t\t// \"none\" = no stored token → full first-time flow (installUrl)\n\t\t\t\tconst reauth = storedAuth.status === \"expired\";\n\t\t\t\tif (reauth) {\n\t\t\t\t\tp.log.warn(\"Stored credentials expired — signing in again\");\n\t\t\t\t} else if (storedAuth.status === \"gone\") {\n\t\t\t\t\tp.log.warn(\"Account not found — starting fresh setup\");\n\t\t\t\t}\n\t\t\t\tconst authResult = await runAuthFlow(\n\t\t\t\t\tapi,\n\t\t\t\t\toptions,\n\t\t\t\t\treauth,\n\t\t\t\t\tidentity?.repoCanonical,\n\t\t\t\t);\n\t\t\t\tif (!authResult) return 1;\n\t\t\t\tuserToken = authResult.token;\n\t\t\t\tuserEmail = authResult.email;\n\t\t\t\tuserName = authResult.name;\n\t\t\t\tauthOrganizationId = authResult.organizationId;\n\n\t\t\t\twriteAuthData({\n\t\t\t\t\ttoken: userToken,\n\t\t\t\t\tuserId: authResult.userId,\n\t\t\t\t\temail: userEmail,\n\t\t\t\t\tname: userName,\n\t\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\t});\n\t\t\t}\n\n\t\t// ── Workspace selection ─────────────────────────────────────────────────────\n\t\tlet selectedWorkspaceId: string;\n\t\tlet selectedWorkspaceName: string;\n\n\t\tif (authOrganizationId) {\n\t\t\t// Install path: auth+install completed in one browser trip, workspace already created.\n\t\t\tconst workspaceData = await api.listWorkspaces(userToken);\n\t\t\tconst ws = workspaceData.workspaces.find(\n\t\t\t\t(w) => w.id === authOrganizationId,\n\t\t\t);\n\t\t\tselectedWorkspaceId = authOrganizationId;\n\t\t\tselectedWorkspaceName = ws?.name ?? userEmail;\n\t\t\tp.log.success(\n\t\t\t\t`Connected as ${chalk.bold(userEmail)} — workspace: ${chalk.bold(selectedWorkspaceName)}`,\n\t\t\t);\n\t\t} else {\n\t\t\t// Always check for cached discovery results first. The cache expires in\n\t\t\t// 5 minutes so returning users (no recent link flow) fall through cleanly.\n\t\t\tconst discoveryResult = await api\n\t\t\t\t.getCliGitHubDiscovery(userToken)\n\t\t\t\t.catch(() => null);\n\t\t\tconst cachedInstallations = discoveryResult?.installations ?? [];\n\n\t\t\tif (cachedInstallations.length > 0) {\n\t\t\t\t// Warn if none of the discovered installations belong to the org that\n\t\t\t\t// owns the current repo — the binding won't be created even if setup succeeds.\n\t\t\t\tif (identity?.repoCanonical) {\n\t\t\t\t\tconst repoOwner = identity.repoCanonical\n\t\t\t\t\t\t.split(\":\")[1]\n\t\t\t\t\t\t?.split(\"/\")[0]\n\t\t\t\t\t\t?.toLowerCase();\n\t\t\t\t\tif (repoOwner) {\n\t\t\t\t\t\tconst hasMatchingAccount = cachedInstallations.some(\n\t\t\t\t\t\t\t(i) => i.accountLogin.toLowerCase() === repoOwner,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!hasMatchingAccount) {\n\t\t\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t\t\t`None of your GitHub App installations belong to \"${repoOwner}\", ` +\n\t\t\t\t\t\t\t\t\t`the account that owns this repository.\\n` +\n\t\t\t\t\t\t\t\t\t` The project will be created but translations won't trigger automatically.\\n` +\n\t\t\t\t\t\t\t\t\t` To fix: install the Vocoder GitHub App on \"${repoOwner}\" instead.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Auto-select when there's exactly one valid (non-suspended, unclaimed) installation\n\t\t\t\tconst validInstallations = cachedInstallations.filter(\n\t\t\t\t\t(i) => !i.isSuspended && !i.conflictLabel,\n\t\t\t\t);\n\n\t\t\t\tlet selectedInstallationId: number | string | null = null;\n\n\t\t\t\tif (\n\t\t\t\t\tvalidInstallations.length === 1 &&\n\t\t\t\t\tcachedInstallations.length === 1\n\t\t\t\t) {\n\t\t\t\t\t// Single installation — claim silently, no prompt needed\n\t\t\t\t\tselectedInstallationId = validInstallations[0]!.installationId;\n\t\t\t\t} else {\n\t\t\t\t\tselectedInstallationId = await selectGitHubInstallation(\n\t\t\t\t\t\tcachedInstallations.map((inst) => ({\n\t\t\t\t\t\t\tinstallationId: inst.installationId,\n\t\t\t\t\t\t\taccountLogin: inst.accountLogin,\n\t\t\t\t\t\t\taccountType: inst.accountType,\n\t\t\t\t\t\t\tisSuspended: inst.isSuspended,\n\t\t\t\t\t\t\tconflictLabel: inst.conflictLabel,\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tselectedInstallationId === null ||\n\t\t\t\t\tselectedInstallationId === \"install_new\"\n\t\t\t\t) {\n\t\t\t\t\tp.cancel(\n\t\t\t\t\t\t\"Setup cancelled. Re-run `vocoder init` and choose Install GitHub App.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tconst claimResult = await api.claimCliGitHubInstallation(userToken, {\n\t\t\t\t\tinstallationId: String(selectedInstallationId),\n\t\t\t\t\torganizationId: null,\n\t\t\t\t});\n\t\t\t\tselectedWorkspaceId = claimResult.organizationId;\n\t\t\t\tselectedWorkspaceName = claimResult.organizationName;\n\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t} else {\n\t\t\t\t// ── Repo-aware workspace resolution ──────────────────────────────────────\n\t\t\t\tconst workspaceData = await api.listWorkspaces(userToken, {\n\t\t\t\t\trepo: identity?.repoCanonical,\n\t\t\t\t});\n\n\t\t\t\tconst repoCanonical = identity?.repoCanonical ?? null;\n\t\t\t\t// Workspaces whose GitHub installation covers the current repo\n\t\t\t\tconst covering = repoCanonical\n\t\t\t\t\t? workspaceData.workspaces.filter((w) => w.coversRepo === true)\n\t\t\t\t\t: [];\n\t\t\t\t// Workspaces that have any GitHub connection (may not cover this repo)\n\t\t\t\tconst connected = workspaceData.workspaces.filter(\n\t\t\t\t\t(w) => w.hasGitHubConnection,\n\t\t\t\t);\n\n\t\t\t\tif (repoCanonical && covering.length === 1) {\n\t\t\t\t\t// ── Scenario 1: exactly one workspace covers this repo — auto-select ──\n\t\t\t\t\tconst ws = covering[0]!;\n\t\t\t\t\tselectedWorkspaceId = ws.id;\n\t\t\t\t\tselectedWorkspaceName = ws.name;\n\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t} else if (repoCanonical && covering.length > 1) {\n\t\t\t\t\t// ── Scenario 2: multiple workspaces cover this repo — let user pick ──\n\t\t\t\t\tconst choice = await p.select<string>({\n\t\t\t\t\t\tmessage: \"Select workspace for this repo\",\n\t\t\t\t\t\toptions: covering.map((w) => ({\n\t\t\t\t\t\t\tvalue: w.id,\n\t\t\t\t\t\t\tlabel: `${w.name} ${chalk.dim(`(${w.projectCount} project${w.projectCount !== 1 ? \"s\" : \"\"})`)}`,\n\t\t\t\t\t\t})),\n\t\t\t\t\t});\n\t\t\t\t\tif (p.isCancel(choice)) {\n\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\tconst ws = covering.find((w) => w.id === choice)!;\n\t\t\t\t\tselectedWorkspaceId = ws.id;\n\t\t\t\t\tselectedWorkspaceName = ws.name;\n\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t} else if (\n\t\t\t\t\trepoCanonical &&\n\t\t\t\t\tcovering.length === 0 &&\n\t\t\t\t\tconnected.length > 0\n\t\t\t\t) {\n\t\t\t\t\t// ── Scenario 3: connected workspaces exist but none cover this repo ──\n\t\t\t\t\tconst shortRepo = repoCanonical.split(\":\")[1] ?? repoCanonical;\n\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t`${chalk.bold(shortRepo)} isn't accessible from your Vocoder installation.\\n` +\n\t\t\t\t\t\t\t` Grant access to this repository or install on the account that owns it.`,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst fixOptions: Array<{ value: string; label: string }> = [];\n\t\t\t\t\tfor (const ws of connected) {\n\t\t\t\t\t\tif (ws.installationConfigureUrl) {\n\t\t\t\t\t\t\tfixOptions.push({\n\t\t\t\t\t\t\t\tvalue: `grant:${ws.id}`,\n\t\t\t\t\t\t\t\tlabel: `Configure ${chalk.bold(ws.connectionLabel ?? ws.name)}'s GitHub App installation`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfixOptions.push({\n\t\t\t\t\t\tvalue: \"install_new\",\n\t\t\t\t\t\tlabel: `Install on a different GitHub account ${chalk.dim(\"(creates a new personal workspace)\")}`,\n\t\t\t\t\t});\n\t\t\t\t\tfixOptions.push({ value: \"cancel\", label: \"Cancel\" });\n\n\t\t\t\t\tconst fix = await p.select<string>({\n\t\t\t\t\t\tmessage: \"How would you like to fix this?\",\n\t\t\t\t\t\toptions: fixOptions,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (p.isCancel(fix) || fix === \"cancel\") {\n\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (fix.startsWith(\"grant:\")) {\n\t\t\t\t\t\tconst ws = connected.find((w) => `grant:${w.id}` === fix)!;\n\t\t\t\t\t\tawait tryOpenBrowser(ws.installationConfigureUrl!);\n\t\t\t\t\t\tp.cancel(\n\t\t\t\t\t\t\t`Grant access to ${chalk.bold(shortRepo)} in your browser,\\n` +\n\t\t\t\t\t\t\t\t` then re-run ${chalk.bold(\"vocoder init\")}.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\n\t\t\t\t\t// install_new: full install → creates new workspace covering the new account\n\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\tapi,\n\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t});\n\t\t\t\t\tif (!connectResult) {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\t\"GitHub App installation did not complete. Run `vocoder init` again.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t} else {\n\t\t\t\t\t// ── Fallback: no repo context or first-time user — standard select ────\n\t\t\t\t\tif (\n\t\t\t\t\t\tworkspaceData.workspaces.length === 1 &&\n\t\t\t\t\t\t!workspaceData.canCreateWorkspace\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst ws = workspaceData.workspaces[0]!;\n\t\t\t\t\t\tselectedWorkspaceId = ws.id;\n\t\t\t\t\t\tselectedWorkspaceName = ws.name;\n\t\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst workspaceResult = await selectWorkspace(workspaceData);\n\n\t\t\t\t\t\tif (workspaceResult.action === \"cancelled\") {\n\t\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (workspaceResult.action === \"use\") {\n\t\t\t\t\t\t\tselectedWorkspaceId = workspaceResult.workspace.id;\n\t\t\t\t\t\t\tselectedWorkspaceName = workspaceResult.workspace.name;\n\t\t\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// ── New workspace: GitHub connect flow ────────────────────────────────\n\t\t\t\t\t\t\tconst connectChoice = await p.select<string>({\n\t\t\t\t\t\t\t\tmessage: \"Connect your new workspace to GitHub\",\n\t\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t\t{ value: \"install\", label: \"Install the Vocoder GitHub App\" },\n\t\t\t\t\t\t\t\t\t{ value: \"link\", label: \"Link an existing installation\" },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (p.isCancel(connectChoice)) {\n\t\t\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (connectChoice === \"install\") {\n\t\t\t\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (!connectResult) {\n\t\t\t\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\t\t\t\t\"GitHub App installation did not complete. Run `vocoder init` again.\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\t\t\t\tp.log.success(\n\t\t\t\t\t\t\t\t\t`Workspace: ${chalk.bold(selectedWorkspaceName)}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst installations = await runGitHubDiscoveryFlow({\n\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (!installations) return 1;\n\n\t\t\t\t\t\t\t\tif (installations.length === 0) {\n\t\t\t\t\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t\t\t\t\t\"No GitHub installations found. Install the Vocoder GitHub App first.\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tconst installNow = await p.confirm({\n\t\t\t\t\t\t\t\t\t\tmessage: \"Open GitHub to install the App?\",\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (p.isCancel(installNow) || !installNow) return 1;\n\t\t\t\t\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (!connectResult) return 1;\n\t\t\t\t\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tconst selectedInstallationId = await selectGitHubInstallation(\n\t\t\t\t\t\t\t\t\t\tinstallations.map((inst) => ({\n\t\t\t\t\t\t\t\t\t\t\tinstallationId: inst.installationId,\n\t\t\t\t\t\t\t\t\t\t\taccountLogin: inst.accountLogin,\n\t\t\t\t\t\t\t\t\t\t\taccountType: inst.accountType,\n\t\t\t\t\t\t\t\t\t\t\tisSuspended: inst.isSuspended,\n\t\t\t\t\t\t\t\t\t\t\tconflictLabel: inst.conflictLabel,\n\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tif (selectedInstallationId === null) {\n\t\t\t\t\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (selectedInstallationId === \"install_new\") {\n\t\t\t\t\t\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tif (!connectResult) return 1;\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst claimResult = await api.claimCliGitHubInstallation(\n\t\t\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tinstallationId: String(selectedInstallationId),\n\t\t\t\t\t\t\t\t\t\t\t\torganizationId: null,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceId = claimResult.organizationId;\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceName = claimResult.organizationName;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tp.log.success(\n\t\t\t\t\t\t\t\t\t`Workspace: ${chalk.bold(selectedWorkspaceName)}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} // closes new workspace else\n\t\t\t\t\t} // closes auto-select else\n\t\t\t\t} // closes main scenario if/else chain\n\t\t\t} // closes cachedInstallations else\n\t\t} // closes if (authOrganizationId) else\n\n\t\t// ── Add-app path: repo already has a project with scoped apps ───────────────\n\t\t// Skip plan limit check — we're adding an App to an existing project,\n\t\t// not creating a new one. Run the project config prompts then call\n\t\t// POST /api/cli/project/apps.\n\t\tif (repoProjectId && repoProjectName && existingAppsForRepo.length > 0) {\n\t\t\tp.log.info(\n\t\t\t\t`${chalk.bold(repoProjectName)} is already set up for this repo.\\n` +\n\t\t\t\t\t` Configured apps: ${existingAppsForRepo\n\t\t\t\t\t\t.map((a) => highlight(a.appDir || \"(entire repo)\"))\n\t\t\t\t\t\t.join(\", \")}`,\n\t\t\t);\n\n\t\t\tconst appResult = await runAppCreate({\n\t\t\t\tapi,\n\t\t\t\tuserToken,\n\t\t\t\tprojectId: repoProjectId,\n\t\t\t\tprojectName: repoProjectName,\n\t\t\t\torganizationName: selectedWorkspaceName,\n\t\t\t\trepoCanonical: identity?.repoCanonical,\n\t\t\t\tdefaultAppDir: identity?.repoAppDir,\n\t\t\t\texistingApps: existingAppsForRepo,\n\t\t\t});\n\n\t\t\tif (!appResult) {\n\t\t\t\tp.log.error(\"App setup failed. Run `vocoder init` again.\");\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\trunScaffold({\n\t\t\t\tsourceLocale: appResult.sourceLocale,\n\t\t\t\ttargetBranches: appResult.targetBranches,\n\t\t\t\tappDir: identity?.repoAppDir,\n\t\t\t});\n\t\t\tp.outro(\"You're all set.\");\n\t\t\treturn 0;\n\t\t}\n\n\t\t// ── Plan limit pre-flight ────────────────────────────────────────────────────\n\t\ttry {\n\t\t\tconst wsCheck = await api.listWorkspaces(userToken);\n\t\t\tconst ws = wsCheck.workspaces.find((w) => w.id === selectedWorkspaceId);\n\t\t\tif (ws && ws.maxProjects !== -1 && ws.projectCount >= ws.maxProjects) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t`Project limit reached — ${ws.projectCount}/${ws.maxProjects} on your ${chalk.bold(ws.planId)} plan.`,\n\t\t\t\t);\n\n\t\t\t\t// \"Connect\" only makes sense when this repo already has a project\n\t\t\t\t// (found by the repo lookup above). Showing all workspace projects\n\t\t\t\t// would let users bind this repo to an unrelated project — invalid\n\t\t\t\t// given the 1:1 project↔repo coupling.\n\t\t\t\tconst options: Array<{ value: string; label: string }> = [];\n\t\t\t\tif (repoProjectId) {\n\t\t\t\t\toptions.push({\n\t\t\t\t\t\tvalue: \"connect\",\n\t\t\t\t\t\tlabel: `Reconnect this repo to ${chalk.bold(repoProjectName ?? \"existing project\")}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\toptions.push({ value: \"upgrade\", label: \"Upgrade plan\" });\n\t\t\t\toptions.push({ value: \"cancel\", label: \"Cancel\" });\n\n\t\t\t\tconst limitAction = await p.select<string>({\n\t\t\t\t\tmessage: \"What would you like to do?\",\n\t\t\t\t\toptions,\n\t\t\t\t});\n\n\t\t\t\tif (p.isCancel(limitAction) || limitAction === \"cancel\") {\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tif (limitAction === \"upgrade\") {\n\t\t\t\t\tawait tryOpenBrowser(`${apiUrl}${SUBSCRIPTION_SETTINGS_PATH}`);\n\t\t\t\t\tp.cancel(\n\t\t\t\t\t\t\"Upgrade your plan in the browser, then re-run `vocoder init`.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\t// connect: fetch existing project config and create App binding without\n\t\t\t\t// prompting — the project already owns sourceLocale/targetBranches.\n\t\t\t\tconst existingProjects = await api.listApps(\n\t\t\t\t\tuserToken,\n\t\t\t\t\tselectedWorkspaceId,\n\t\t\t\t);\n\t\t\t\tconst chosenProject = existingProjects.find(\n\t\t\t\t\t(proj) => proj.id === repoProjectId,\n\t\t\t\t);\n\t\t\t\tif (!chosenProject) {\n\t\t\t\t\tp.log.error(\"Could not find the project. Try again.\");\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst appResult = await api.createApp(userToken, {\n\t\t\t\t\t\tprojectId: chosenProject.id,\n\t\t\t\t\t\tappDir: identity?.repoAppDir ?? \"\",\n\t\t\t\t\t\tsourceLocale: chosenProject.sourceLocale,\n\t\t\t\t\t\ttargetLocales: chosenProject.targetLocales,\n\t\t\t\t\t\ttargetBranches: chosenProject.targetBranches,\n\t\t\t\t\t\trepoCanonical: identity?.repoCanonical ?? \"\",\n\t\t\t\t\t});\n\t\t\t\t\tp.log.success(`Connected to project: ${chalk.bold(chosenProject.name)}`);\n\t\t\t\t\tprintApiKey(appResult.apiKey);\n\t\t\t\t\trunScaffold({\n\t\t\t\t\t\tsourceLocale: chosenProject.sourceLocale,\n\t\t\t\t\t\ttargetBranches: chosenProject.targetBranches,\n\t\t\t\t\t\tappDir: identity?.repoAppDir,\n\t\t\t\t\t});\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\tp.log.error(`Failed to create app binding: ${msg}`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tp.outro(\"You're all set.\");\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Non-fatal\n\t\t}\n\n\t\t// ── Project configuration ────────────────────────────────────────────────────\n\t\tconst projectResult = await runProjectCreate({\n\t\t\tapi,\n\t\t\tuserToken,\n\t\t\torganizationId: selectedWorkspaceId,\n\t\t\tdefaultName: identity?.repoCanonical\n\t\t\t\t? identity.repoCanonical.split(\"/\").pop()\n\t\t\t\t: undefined,\n\t\t\tdefaultSourceLocale: \"en\",\n\t\t\trepoCanonical: identity?.repoCanonical,\n\t\t\tdefaultBranches: [\"main\"],\n\t\t\tdefaultAppDir: identity?.repoAppDir,\n\t\t});\n\n\t\tif (!projectResult) {\n\t\t\tp.log.error(\"Project creation failed. Run `vocoder init` again.\");\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Warn if the current repo isn't accessible to the GitHub App installation.\n\t\t// This means translations won't trigger on push until the App is granted access.\n\t\tif (!projectResult.repositoryBound && identity?.repoCanonical) {\n\t\t\tp.log.warn(\n\t\t\t\t`This repository isn't accessible to your GitHub App installation.\\n` +\n\t\t\t\t\t`Translations won't run automatically until you grant access.\\n\\n` +\n\t\t\t\t\t` To fix: go to your GitHub App installation settings and add this\\n` +\n\t\t\t\t\t` repository to the allowed list, or switch to \"All repositories\".\\n` +\n\t\t\t\t\t(projectResult.configureUrl\n\t\t\t\t\t\t? `\\n ${chalk.dim(projectResult.configureUrl)}\\n`\n\t\t\t\t\t\t: \"\"),\n\t\t\t);\n\t\t}\n\n\t\t// ── Scaffold + API key ───────────────────────────────────────────────────────\n\t\trunScaffold({\n\t\t\tsourceLocale: projectResult.sourceLocale,\n\t\t\ttargetBranches: projectResult.targetBranches,\n\t\t\tappDir: identity?.repoAppDir,\n\t\t});\n\n\t\tprintApiKey(projectResult.apiKey);\n\n\t\tp.outro(\"You're all set.\");\n\t\treturn 0;\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tif (isPlanLimitFailure(error.message)) {\n\t\t\t\tprintPlanLimitMessage(apiUrl, error.message);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tp.log.error(`Error: ${error.message}`);\n\t\t} else {\n\t\t\tp.log.error(\"Unknown setup error\");\n\t\t}\n\n\t\treturn 1;\n\t}\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Returns the path of an existing vocoder.config file in cwd, trying\n * .ts → .js → .json in order. Returns null when none is found.\n */\nexport function findExistingConfig(cwd: string = process.cwd()): string | null {\n\tfor (const name of [\n\t\t\"vocoder.config.ts\",\n\t\t\"vocoder.config.js\",\n\t\t\"vocoder.config.json\",\n\t]) {\n\t\tconst candidate = join(cwd, name);\n\t\tif (existsSync(candidate)) return candidate;\n\t}\n\treturn null;\n}\n\n/**\n * Write a vocoder.config file to cwd if one doesn't already exist.\n * Pass `useTypeScript: false` for plain-JS projects — writes vocoder.config.js\n * instead of vocoder.config.ts. The config content is identical; only the\n * file extension (and therefore the import style in the user's editor) differs.\n *\n * Returns the filename that was written, or null if the file already existed\n * or the write failed.\n */\nexport function writeVocoderConfig(options: {\n\ttargetBranches?: string[];\n\tuseTypeScript?: boolean;\n\tcwd?: string;\n}): string | null {\n\tconst {\n\t\ttargetBranches = [\"main\"],\n\t\tuseTypeScript = true,\n\t\tcwd = process.cwd(),\n\t} = options;\n\n\t// Don't write if any config variant already exists\n\tif (findExistingConfig(cwd)) return null;\n\n\tconst ext = useTypeScript ? \"ts\" : \"js\";\n\tconst configPath = join(cwd, `vocoder.config.${ext}`);\n\tconst branchesStr = targetBranches.map((b) => `'${b}'`).join(\", \");\n\n\t// Patterns are always relative to the config file's own directory.\n\t// In a monorepo, the config lives in the app subdirectory, so `**` naturally\n\t// scopes to that app — no `appDir/` prefix needed (and adding it would break\n\t// extraction when the CLI or build plugin runs with the app dir as cwd).\n\tconst includes = [\"**/*.{tsx,jsx,ts,js}\"];\n\tconst includesStr = includes.map((p) => `'${p}'`).join(\", \");\n\n\t// Both TS and JS use ESM import syntax — the content is identical.\n\t// TypeScript users get type-checking from defineConfig; JS users get\n\t// the same runtime behaviour with no TS toolchain required.\n\tconst content = `import { defineConfig } from '@vocoder/config'\n\nexport default defineConfig({\n targetBranches: [${branchesStr}],\n include: [${includesStr}],\n})\n`;\n\n\ttry {\n\t\twriteFileSync(configPath, content, \"utf-8\");\n\t\treturn `vocoder.config.${ext}`;\n\t} catch {\n\t\treturn null;\n\t}\n}\n","import { spawn } from \"node:child_process\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport type { VocoderAPI } from \"./api.js\";\nimport { startCallbackServer } from \"./local-server.js\";\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n\tif (!process.stdout.isTTY || process.env.CI === \"true\") {\n\t\treturn false;\n\t}\n\n\tconst platform = process.platform;\n\tlet command: string;\n\tlet args: string[];\n\n\tif (platform === \"darwin\") {\n\t\tcommand = \"open\";\n\t\targs = [url];\n\t} else if (platform === \"win32\") {\n\t\tcommand = \"rundll32\";\n\t\targs = [\"url.dll,FileProtocolHandler\", url];\n\t} else {\n\t\tcommand = \"xdg-open\";\n\t\targs = [url];\n\t}\n\n\treturn new Promise<boolean>((resolve) => {\n\t\ttry {\n\t\t\tconst child = spawn(command, args, {\n\t\t\t\tdetached: true,\n\t\t\t\tstdio: \"ignore\",\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\n\t\t\tlet settled = false;\n\t\t\tchild.once(\"spawn\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tchild.unref();\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t\tchild.once(\"error\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t});\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t}, 300);\n\t\t} catch {\n\t\t\tresolve(false);\n\t\t}\n\t});\n}\n\nexport interface GitHubConnectResult {\n\torganizationId: string;\n\torganizationName: string;\n\tconnectionLabel: string;\n}\n\n/**\n * Run the full GitHub App install flow for a new workspace.\n * Opens the browser to the GitHub App install page and waits for completion.\n *\n * Returns `null` if the user cancelled or an error occurred.\n */\nexport async function runGitHubInstallFlow(params: {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\torganizationId?: string;\n\tyes?: boolean;\n}): Promise<GitHubConnectResult | null> {\n\t// Try to start a local callback server for instant notification\n\tlet server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n\ttry {\n\t\tserver = await startCallbackServer();\n\t} catch {\n\t\t// Fall through — the user can re-run if something goes wrong\n\t}\n\n\tconst { installUrl } = await params.api.startCliGitHubInstall(\n\t\tparams.userToken,\n\t\t{\n\t\t\torganizationId: params.organizationId,\n\t\t\tcallbackPort: server?.port,\n\t\t},\n\t);\n\n\tp.log.info(\"Opening GitHub to install the Vocoder App...\");\n\tp.note(installUrl, \"Install URL\");\n\n\tif (\n\t\tprocess.stdin.isTTY &&\n\t\tprocess.stdout.isTTY &&\n\t\tprocess.env.CI !== \"true\"\n\t) {\n\t\tconst shouldOpen = params.yes\n\t\t\t? true\n\t\t\t: await p.confirm({ message: \"Open in your browser?\" });\n\n\t\tif (p.isCancel(shouldOpen)) {\n\t\t\tserver?.close();\n\t\t\treturn null;\n\t\t}\n\n\t\tif (shouldOpen) {\n\t\t\tconst opened = await tryOpenBrowser(installUrl);\n\t\t\tif (!opened) {\n\t\t\t\tp.log.info(\n\t\t\t\t\t\"Could not open a browser automatically. Use the URL above.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst connectSpinner = p.spinner();\n\tconnectSpinner.start(\"Waiting for GitHub App installation...\");\n\n\tif (server) {\n\t\ttry {\n\t\t\tconst params_timeout = 15 * 60 * 1000; // 15 minutes\n\t\t\tconst callbackParams = await Promise.race([\n\t\t\t\tserver.waitForCallback(),\n\t\t\t\tnew Promise<null>((resolve) =>\n\t\t\t\t\tsetTimeout(() => resolve(null), params_timeout),\n\t\t\t\t),\n\t\t\t]);\n\n\t\t\tserver.close();\n\n\t\t\tif (!callbackParams) {\n\t\t\t\tconnectSpinner.stop(\"GitHub App installation timed out\");\n\t\t\t\tp.log.error(\n\t\t\t\t\t\"The installation flow timed out. Run `vocoder init` again.\",\n\t\t\t\t);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (callbackParams.error) {\n\t\t\t\tconnectSpinner.stop(\"GitHub App installation failed\");\n\t\t\t\tp.log.error(callbackParams.error);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { organizationId, connectionLabel, workspace_created } =\n\t\t\t\tcallbackParams;\n\n\t\t\tif (!organizationId || !connectionLabel) {\n\t\t\t\tconnectSpinner.stop(\"GitHub App installation incomplete\");\n\t\t\t\tp.log.error(\"Missing organization or connection data from callback.\");\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconnectSpinner.stop(\n\t\t\t\t`Connected to GitHub as ${chalk.bold(connectionLabel)}`,\n\t\t\t);\n\n\t\t\t// Fetch the org name\n\t\t\tconst orgName = workspace_created ? connectionLabel : organizationId;\n\t\t\treturn {\n\t\t\t\torganizationId,\n\t\t\t\torganizationName: orgName,\n\t\t\t\tconnectionLabel,\n\t\t\t};\n\t\t} catch {\n\t\t\tserver.close();\n\t\t\tconnectSpinner.stop(\"GitHub App installation failed\");\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// No local server — there's no polling fallback for install; just wait\n\tconnectSpinner.stop(\"Could not detect GitHub App installation automatically\");\n\tp.log.warn(\n\t\t\"Complete the installation in your browser, then run `vocoder init` again.\",\n\t);\n\treturn null;\n}\n\n/**\n * Run the GitHub OAuth discovery flow to find existing installations.\n * Returns the list of installations with conflict labels, or null on cancellation/error.\n */\nexport async function runGitHubDiscoveryFlow(params: {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\torganizationId?: string;\n\tyes?: boolean;\n}): Promise<Array<{\n\tinstallationId: number;\n\taccountLogin: string;\n\taccountType: string;\n\tisSuspended: boolean;\n\tconflictLabel: string | null;\n}> | null> {\n\t// Try local callback server\n\tlet server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n\ttry {\n\t\tserver = await startCallbackServer();\n\t} catch {\n\t\t// Fall through\n\t}\n\n\tconst { oauthUrl } = await params.api.startCliGitHubOAuth(params.userToken, {\n\t\torganizationId: params.organizationId,\n\t\tcallbackPort: server?.port,\n\t});\n\n\tp.log.info(\"Opening GitHub to authorize your account...\");\n\tp.note(\"Complete authorization in your browser.\");\n\n\tif (\n\t\tprocess.stdin.isTTY &&\n\t\tprocess.stdout.isTTY &&\n\t\tprocess.env.CI !== \"true\"\n\t) {\n\t\tconst shouldOpen = params.yes\n\t\t\t? true\n\t\t\t: await p.confirm({ message: \"Open in your browser?\" });\n\n\t\tif (p.isCancel(shouldOpen)) {\n\t\t\tserver?.close();\n\t\t\treturn null;\n\t\t}\n\n\t\tif (shouldOpen) {\n\t\t\tconst opened = await tryOpenBrowser(oauthUrl);\n\t\t\tif (!opened) {\n\t\t\t\tp.log.info(`Could not open browser automatically. Visit: ${oauthUrl}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst oauthSpinner = p.spinner();\n\toauthSpinner.start(\"Waiting for GitHub authorization...\");\n\n\tif (server) {\n\t\ttry {\n\t\t\tconst timeoutMs = 10 * 60 * 1000;\n\t\t\tconst callbackParams = await Promise.race([\n\t\t\t\tserver.waitForCallback(),\n\t\t\t\tnew Promise<null>((resolve) =>\n\t\t\t\t\tsetTimeout(() => resolve(null), timeoutMs),\n\t\t\t\t),\n\t\t\t]);\n\n\t\t\tserver.close();\n\n\t\t\tif (!callbackParams) {\n\t\t\t\toauthSpinner.stop(\"GitHub authorization timed out\");\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (callbackParams.error) {\n\t\t\t\toauthSpinner.stop(\"GitHub authorization failed\");\n\t\t\t\tp.log.error(callbackParams.error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} catch {\n\t\t\tserver.close();\n\t\t\toauthSpinner.stop(\"GitHub authorization failed\");\n\t\t\treturn null;\n\t\t}\n\t}\n\n\toauthSpinner.stop(\"GitHub account authorized\");\n\n\t// Fetch discovery results\n\tconst discoveryResult = await params.api.getCliGitHubDiscovery(\n\t\tparams.userToken,\n\t);\n\treturn discoveryResult.installations;\n}\n\ntype DiscoveredInstallation = {\n\tinstallationId: number;\n\taccountLogin: string;\n\taccountType: string;\n\tisSuspended: boolean;\n\tconflictLabel: string | null;\n};\n\n/**\n * Prompt the user to select a GitHub installation from discovery results.\n * Returns the selected installation ID, 'install_new' to trigger install flow,\n * or null on cancellation.\n */\nexport async function selectGitHubInstallation(\n\tinstallations: DiscoveredInstallation[],\n\tcanInstallNew: boolean,\n): Promise<number | \"install_new\" | null> {\n\ttype SelectValue = string;\n\n\tconst options: Array<{ value: SelectValue; label: string; hint?: string }> =\n\t\tinstallations.map((inst) => ({\n\t\t\tvalue: String(inst.installationId),\n\t\t\tlabel: inst.accountLogin,\n\t\t\thint:\n\t\t\t\t[\n\t\t\t\t\tinst.accountType === \"Organization\" ? \"organization\" : \"personal\",\n\t\t\t\t\tinst.conflictLabel ? `connected to ${inst.conflictLabel}` : \"\",\n\t\t\t\t\tinst.isSuspended ? \"suspended\" : \"\",\n\t\t\t\t]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join(\" · \") || undefined,\n\t\t}));\n\n\tif (canInstallNew) {\n\t\toptions.push({\n\t\t\tvalue: \"install_new\",\n\t\t\tlabel: `Install on a new account ${chalk.dim(\"(creates a new personal workspace)\")}`,\n\t\t});\n\t}\n\n\tconst selected = await p.select<SelectValue>({\n\t\tmessage: \"Select a GitHub installation\",\n\t\toptions,\n\t});\n\n\tif (p.isCancel(selected)) return null;\n\tif (selected === \"install_new\") return \"install_new\";\n\n\treturn Number(selected);\n}\n","import { createServer } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { URL } from \"node:url\";\n\nexport interface LocalServerHandle {\n\tport: number;\n\twaitForCallback: () => Promise<Record<string, string>>;\n\tclose: () => void;\n}\n\n/**\n * Starts a local HTTP server on a random available port.\n * Returns the port and a promise that resolves when the browser\n * redirects to /callback with query parameters.\n *\n * Used for the browser→CLI token handoff pattern:\n * 1. CLI passes `port` to the auth session start request\n * 2. After browser auth, vocoder.app redirects to localhost:<port>/callback?token=...\n * 3. `waitForCallback()` resolves with the query params\n */\nexport function startCallbackServer(): Promise<LocalServerHandle> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tlet callbackResolve: ((params: Record<string, string>) => void) | null =\n\t\t\tnull;\n\t\tlet callbackReject: ((err: Error) => void) | null = null;\n\n\t\tconst callbackPromise = new Promise<Record<string, string>>((res, rej) => {\n\t\t\tcallbackResolve = res;\n\t\t\tcallbackReject = rej;\n\t\t});\n\n\t\tconst server = createServer((req, res) => {\n\t\t\tif (!req.url) {\n\t\t\t\tres.writeHead(400);\n\t\t\t\tres.end();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet pathname: string;\n\t\t\tlet params: Record<string, string>;\n\n\t\t\ttry {\n\t\t\t\tconst parsed = new URL(req.url, \"http://localhost\");\n\t\t\t\tpathname = parsed.pathname;\n\t\t\t\tparams = Object.fromEntries(parsed.searchParams.entries());\n\t\t\t} catch {\n\t\t\t\tres.writeHead(400);\n\t\t\t\tres.end(\"Bad request\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (pathname !== \"/callback\") {\n\t\t\t\tres.writeHead(404);\n\t\t\t\tres.end(\"Not found\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tres.writeHead(200, { \"Content-Type\": \"text/html\" });\n\t\t\tres.end(\n\t\t\t\t\"<!DOCTYPE html><html><head><title>Authenticated</title></head>\" +\n\t\t\t\t\t'<body style=\"font-family:sans-serif;text-align:center;padding:3rem;\">' +\n\t\t\t\t\t\"<h2>Authenticated</h2>\" +\n\t\t\t\t\t\"<p>Return to your terminal to continue. You can close this tab.</p>\" +\n\t\t\t\t\t\"</body></html>\",\n\t\t\t);\n\n\t\t\tif (callbackResolve) {\n\t\t\t\tcallbackResolve(params);\n\t\t\t\tcallbackResolve = null;\n\t\t\t}\n\n\t\t\tsetImmediate(() => server.close());\n\t\t});\n\n\t\tserver.on(\"error\", (err) => {\n\t\t\tif (!settled) {\n\t\t\t\tsettled = true;\n\t\t\t\tif (callbackReject) callbackReject(err);\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\n\t\t// Bind to a random port on localhost only\n\t\tserver.listen(0, \"127.0.0.1\", () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\n\t\t\tconst port = (server.address() as AddressInfo).port;\n\n\t\t\tresolve({\n\t\t\t\tport,\n\t\t\t\twaitForCallback: () => callbackPromise,\n\t\t\t\tclose: () => server.close(),\n\t\t\t});\n\t\t});\n\t});\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport type { VocoderAPI } from \"./api.js\";\nimport { detectGitBranches, filterableBranchSelect } from \"./branch-select.js\";\nimport type { LocaleOption } from \"./locale-search.js\";\nimport {\n\tsearchMultiSelectLocales,\n\tsearchSelectLocale,\n} from \"./locale-search.js\";\n\nexport interface ExistingApp {\n\tappDir: string;\n\tprojectId: string;\n\tprojectName: string;\n\torganizationName: string;\n}\n\nexport interface ProjectCreateParams {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\torganizationId: string;\n\t/** Default project name (repo name or directory name) */\n\tdefaultName?: string;\n\t/** Pre-detected source locale, e.g. \"en\" */\n\tdefaultSourceLocale?: string;\n\t/** Repo canonical for binding the project, e.g. \"github:owner/repo\" */\n\trepoCanonical?: string;\n\t/** Default target branches */\n\tdefaultBranches?: string[];\n\t/**\n\t * Auto-detected scope path (CWD relative to git root).\n\t * Non-empty when running from a subdirectory of the repo — monorepo use case.\n\t * e.g. \"apps/web\"\n\t */\n\tdefaultAppDir?: string;\n}\n\nexport interface AppCreateParams {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\tprojectId: string;\n\tprojectName: string;\n\torganizationName: string;\n\trepoCanonical?: string;\n\tdefaultAppDir?: string;\n\t/** Existing apps to display and validate against */\n\texistingApps: ExistingApp[];\n}\n\nexport interface AppCreateResult {\n\tprojectId: string;\n\tprojectName: string;\n\tapiKey: string;\n\tappDir: string;\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\ttargetBranches: string[];\n}\n\nexport interface ProjectCreateResult {\n\tprojectId: string;\n\tprojectName: string;\n\tapiKey: string;\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\ttargetBranches: string[];\n\trepositoryBound: boolean;\n\tconfigureUrl?: string;\n}\n\n/** All locales — used for target language selection. */\nfunction buildLocaleOptions(\n\tlocales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n\treturn locales.map((l) => ({\n\t\tbcp47: l.code,\n\t\tlabel: `${l.name} — ${l.code}`,\n\t}));\n}\n\n/**\n * Deduplicated language list — used for source language selection.\n * Groups locales by language family (prefix before first hyphen) and keeps one\n * representative per family, preferring the shortest/base code (e.g. \"en\" over\n * \"en-US\"). This prevents showing \"English\", \"English (American)\", \"English\n * (British)\" as three separate choices when the user just means \"English\".\n */\nfunction buildLanguageOptions(\n\tlocales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n\tconst byFamily = new Map<string, LocaleOption>();\n\n\tfor (const l of locales) {\n\t\tconst family = l.code.split(\"-\")[0]!.toLowerCase();\n\t\tconst opt: LocaleOption = { bcp47: l.code, label: `${l.name} — ${l.code}` };\n\t\tconst existing = byFamily.get(family);\n\t\t// Prefer base code (shorter, no region suffix) over regional variants\n\t\tif (!existing || l.code.length < existing.bcp47.length) {\n\t\t\tbyFamily.set(family, opt);\n\t\t}\n\t}\n\n\treturn Array.from(byFamily.values());\n}\n\n/**\n * Run the full project configuration TUI: prompts for name, source locale,\n * target locales, and target branches, then calls POST /api/cli/projects.\n *\n * Returns the created project info (including API key), or null if cancelled.\n */\nexport async function runProjectCreate(\n\tparams: ProjectCreateParams,\n): Promise<ProjectCreateResult | null> {\n\tconst { api, userToken, organizationId, repoCanonical } = params;\n\n\t// ── Project name ────────────────────────────────────────────────────────────\n\t// Use the detected repo name automatically — no prompt needed.\n\tconst projectName = (params.defaultName ?? \"my-project\").trim();\n\tp.log.success(`Project: ${chalk.bold(projectName)}`);\n\n\t// ── Fetch source locales ────────────────────────────────────────────────────\n\tlet sourceLocales: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\t({ sourceLocales } = await api.listLocales(userToken));\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch supported locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst languageOptions = buildLanguageOptions(sourceLocales);\n\n\t// ── Scope path (monorepo) ───────────────────────────────────────────────────\n\tconst appDir = params.defaultAppDir ?? \"\";\n\tif (appDir) {\n\t\tp.log.success(`App directory: ${chalk.bold(appDir)}`);\n\t}\n\n\t// ── Source locale ───────────────────────────────────────────────────────────\n\tconst sourceLocale = await searchSelectLocale(\n\t\tlanguageOptions,\n\t\t\"Source language (the language your code is written in)\",\n\t\tparams.defaultSourceLocale ?? \"en\",\n\t);\n\n\tif (sourceLocale === null) return null;\n\n\t// ── Compatible target locales (fetched after source is known) ───────────────\n\tlet compatibleTargets: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\tcompatibleTargets = await api.listCompatibleLocales(userToken, sourceLocale);\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch compatible target locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst localeOptions = buildLocaleOptions(compatibleTargets);\n\n\t// ── Target locales ──────────────────────────────────────────────────────────\n\tconst targetOptions = localeOptions.filter(\n\t\t(opt) => opt.bcp47 !== sourceLocale,\n\t);\n\n\tconst targetLocales = await searchMultiSelectLocales(\n\t\ttargetOptions,\n\t\t\"Target languages (languages to translate into)\",\n\t);\n\n\tif (targetLocales === null) return null;\n\n\tif (targetLocales.length === 0) {\n\t\tp.log.warn(\n\t\t\t\"No target languages selected — you can add them later from the dashboard.\",\n\t\t);\n\t}\n\n\t// ── Branch triggers — per-trigger selection ────────────────────────────────\n\t// Ask which branches should fire for each trigger type. Branches can appear\n\t// in both push and PR (they get both triggers). Manual is mutually exclusive:\n\t// a branch cannot be both automatic (push/PR) and manual-only.\n\tconst detected = detectGitBranches();\n\tconst initialBranches = params.defaultBranches?.length\n\t\t? params.defaultBranches\n\t\t: [detected.defaultBranch];\n\n\t// Step 1: push (required)\n\tlet pushBranches: string[] = [];\n\t{\n\t\tlet initial = initialBranches;\n\t\twhile (pushBranches.length === 0) {\n\t\t\tconst result = await filterableBranchSelect({\n\t\t\t\tmessage: \"Which branches should trigger translations?\",\n\t\t\t\tbranches: detected.branches,\n\t\t\t\tdefaultBranch: detected.defaultBranch,\n\t\t\t\tinitialValues: initial,\n\t\t\t});\n\t\t\tif (result === null) return null;\n\t\t\tif (result.length === 0) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t\"At least one branch is required. Please select at least one.\",\n\t\t\t\t);\n\t\t\t\tinitial = [detected.defaultBranch];\n\t\t\t} else {\n\t\t\t\tpushBranches = result;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst targetBranches = pushBranches;\n\n\t// ── Create project ──────────────────────────────────────────────────────────\n\ttry {\n\t\tconst result = await api.createProject(userToken, {\n\t\t\torganizationId,\n\t\t\tname: projectName,\n\t\t\tsourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t\tappDirs: appDir ? [appDir] : [],\n\t\t\trepoCanonical,\n\t\t});\n\n\t\tp.log.success(`Project ${chalk.bold(result.projectName)} created!`);\n\t\treturn result;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"Unknown error\";\n\t\tp.log.error(`Failed to create project: ${message}`);\n\t\treturn null;\n\t}\n}\n\n/**\n * Configure and create a new App under an existing project.\n * Used when the repo already has a project (monorepo: adding a new app directory).\n * No plan limit check runs — only a new App is created, not a new Project.\n */\nexport async function runAppCreate(\n\tparams: AppCreateParams,\n): Promise<AppCreateResult | null> {\n\tconst { api, userToken, projectId, projectName, repoCanonical } = params;\n\tconst existingScopes = new Set(params.existingApps.map((a) => a.appDir));\n\n\t// ── Fetch source locales ────────────────────────────────────────────────────\n\tlet sourceLocales: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\t({ sourceLocales } = await api.listLocales(userToken));\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch supported locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst languageOptions = buildLanguageOptions(sourceLocales);\n\n\t// ── App directory ───────────────────────────────────────────────────────────\n\tconst appDir = params.defaultAppDir ?? \"\";\n\tif (existingScopes.has(appDir)) {\n\t\tp.log.error(`App directory \"${appDir}\" is already configured for this project.`);\n\t\treturn null;\n\t}\n\tif (appDir) {\n\t\tp.log.success(`App directory: ${chalk.bold(appDir)}`);\n\t}\n\n\t// ── Source locale ───────────────────────────────────────────────────────────\n\tconst sourceLocale = await searchSelectLocale(\n\t\tlanguageOptions,\n\t\t\"Source language\",\n\t\t\"en\",\n\t);\n\tif (sourceLocale === null) return null;\n\n\t// ── Compatible target locales (fetched after source is known) ───────────────\n\tlet compatibleTargets: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\tcompatibleTargets = await api.listCompatibleLocales(userToken, sourceLocale);\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch compatible target locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\t// ── Target locales ──────────────────────────────────────────────────────────\n\tconst targetOptions = buildLocaleOptions(compatibleTargets).filter(\n\t\t(opt) => opt.bcp47 !== sourceLocale,\n\t);\n\tconst targetLocales = await searchMultiSelectLocales(\n\t\ttargetOptions,\n\t\t\"Target languages\",\n\t);\n\tif (targetLocales === null) return null;\n\tif (targetLocales.length === 0) {\n\t\tp.log.warn(\n\t\t\t\"No target languages selected — you can add them later from the dashboard.\",\n\t\t);\n\t}\n\n\t// ── Branch triggers — per-trigger selection (same logic as runProjectCreate) ─\n\tconst detectedApp = detectGitBranches();\n\n\tlet appPushBranches: string[] = [];\n\t{\n\t\tlet initial = [detectedApp.defaultBranch];\n\t\twhile (appPushBranches.length === 0) {\n\t\t\tconst result = await filterableBranchSelect({\n\t\t\t\tmessage: \"Which branches should trigger translations?\",\n\t\t\t\tbranches: detectedApp.branches,\n\t\t\t\tdefaultBranch: detectedApp.defaultBranch,\n\t\t\t\tinitialValues: initial,\n\t\t\t});\n\t\t\tif (result === null) return null;\n\t\t\tif (result.length === 0) {\n\t\t\t\tp.log.warn(\"At least one branch is required.\");\n\t\t\t\tinitial = [detectedApp.defaultBranch];\n\t\t\t} else {\n\t\t\t\tappPushBranches = result;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst targetBranches = appPushBranches;\n\n\t// ── Create the App ─────────────────────────────────────────────────────────\n\ttry {\n\t\tconst result = await api.createProject(userToken, {\n\t\t\tprojectId,\n\t\t\tappDir,\n\t\t\tsourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t\trepoCanonical: repoCanonical ?? \"\",\n\t\t});\n\n\t\tp.log.success(\n\t\t\t`App ${chalk.bold(appDir)} added to ${chalk.bold(projectName)}!`,\n\t\t);\n\t\treturn {\n\t\t\tprojectId: result.projectId,\n\t\t\tprojectName: result.projectName,\n\t\t\tapiKey: result.apiKey,\n\t\t\tappDir: result.appDir,\n\t\t\tsourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"Unknown error\";\n\t\tp.log.error(`Failed to add app: ${message}`);\n\t\treturn null;\n\t}\n}\n","import { execSync } from \"node:child_process\";\nimport { isCancel, Prompt } from \"@clack/core\";\nimport { active, bld, dim, grn, info, red, ylw } from \"./theme.js\";\n\n// ── Symbols ───────────────────────────────────────────────────────────────────\n\nconst S_BAR = \"│\";\nconst S_BAR_END = \"└\";\nconst S_ACTIVE = \"◆\";\nconst S_SUBMIT = \"◆\";\nconst S_CANCEL = \"■\";\nconst S_ERROR = \"▲\";\n\nfunction symbol(state: string): string {\n\tswitch (state) {\n\t\tcase \"submit\":\n\t\t\treturn grn(S_SUBMIT);\n\t\tcase \"cancel\":\n\t\t\treturn red(S_CANCEL);\n\t\tcase \"error\":\n\t\t\treturn ylw(S_ERROR);\n\t\tdefault:\n\t\t\treturn active(S_ACTIVE);\n\t}\n}\n\n// ── Git detection ─────────────────────────────────────────────────────────────\n\nexport interface DetectedBranches {\n\tbranches: string[];\n\tdefaultBranch: string;\n}\n\nexport function detectGitBranches(cwd?: string): DetectedBranches {\n\tconst workDir = cwd ?? process.cwd();\n\ttry {\n\t\t// Local branches\n\t\tconst localOut = execSync(\"git branch\", {\n\t\t\tcwd: workDir,\n\t\t\tstdio: \"pipe\",\n\t\t}).toString();\n\t\tconst localBranches = localOut\n\t\t\t.split(\"\\n\")\n\t\t\t.filter(Boolean)\n\t\t\t.map((b) => b.replace(/^\\*?\\s*/, \"\").trim())\n\t\t\t.filter(Boolean);\n\n\t\t// Remote branches (strip \"origin/\" prefix, skip HEAD pointer)\n\t\tlet remoteBranches: string[] = [];\n\t\ttry {\n\t\t\tconst remoteOut = execSync(\"git branch -r\", {\n\t\t\t\tcwd: workDir,\n\t\t\t\tstdio: \"pipe\",\n\t\t\t}).toString();\n\t\t\tremoteBranches = remoteOut\n\t\t\t\t.split(\"\\n\")\n\t\t\t\t.map((b) => b.trim())\n\t\t\t\t.filter((b) => b && !b.includes(\"HEAD\"))\n\t\t\t\t.map((b) => b.replace(/^[^/]+\\//, \"\")); // strip \"origin/\" (or any remote name)\n\t\t} catch {\n\t\t\t/* no remote */\n\t\t}\n\n\t\tconst branches = [...new Set([...localBranches, ...remoteBranches])].sort();\n\n\t\t// Default branch: ask git for origin's HEAD (local cache, no network call).\n\t\t// Falls back to 'main' if the remote HEAD isn't cached.\n\t\tlet defaultBranch = \"main\";\n\t\ttry {\n\t\t\tconst ref = execSync(\"git symbolic-ref refs/remotes/origin/HEAD\", {\n\t\t\t\tcwd: workDir,\n\t\t\t\tstdio: \"pipe\",\n\t\t\t})\n\t\t\t\t.toString()\n\t\t\t\t.trim();\n\t\t\t// ref = \"refs/remotes/origin/main\"\n\t\t\tdefaultBranch = ref.split(\"/\").pop() ?? \"main\";\n\t\t} catch {\n\t\t\t/* HEAD not cached — run \"git remote set-head origin --auto\" to fix */\n\t\t}\n\n\t\treturn {\n\t\t\tbranches: branches.length > 0 ? branches : [defaultBranch],\n\t\t\tdefaultBranch,\n\t\t};\n\t} catch {\n\t\treturn { branches: [\"main\"], defaultBranch: \"main\" };\n\t}\n}\n\n// ── Validation ────────────────────────────────────────────────────────────────\n\nconst INVALID_CHARS = /[\\s?^~:[\\]\\\\]/;\n\nexport function validateBranchPattern(pattern: string): string | null {\n\tconst t = pattern.trim();\n\tif (!t) return \"Pattern cannot be empty\";\n\tif (INVALID_CHARS.test(t))\n\t\treturn \"Invalid characters — avoid spaces, ?, ^, ~, :, [, ], \\\\\";\n\tif (t.startsWith(\"/\") || t.endsWith(\"/\")) return \"Cannot start or end with /\";\n\tif (t.includes(\"//\")) return \"Cannot contain //\";\n\treturn null;\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 10;\nconst _ADD_PATTERN_VALUE = \"__add__\";\n\ninterface BranchItem {\n\tvalue: string;\n\tlabel: string;\n\tisCustom?: boolean;\n}\n\nfunction buildItems(\n\tbranches: string[],\n\tdefaultBranch: string,\n\tcustomPatterns: string[],\n): BranchItem[] {\n\tconst items: BranchItem[] = branches.map((b) => ({\n\t\tvalue: b,\n\t\tlabel: b === defaultBranch ? `${b} (default branch)` : b,\n\t}));\n\tfor (const pt of customPatterns) {\n\t\tif (!branches.includes(pt)) {\n\t\t\titems.push({ value: pt, label: pt, isCustom: true });\n\t\t}\n\t}\n\treturn items;\n}\n\nfunction filterItems(items: BranchItem[], query: string): BranchItem[] {\n\tif (!query.trim()) return items;\n\tconst lower = query.toLowerCase();\n\treturn items.filter((i) => i.value.toLowerCase().includes(lower));\n}\n\nfunction buildList(\n\tfiltered: BranchItem[],\n\tcursor: number,\n\tscrollOffset: number,\n\tselected: Set<string>,\n\tfilter: string,\n\tcustomPatterns: string[],\n\taddCursor: boolean,\n\toptional = false,\n\texcludedPatterns: Set<string> = new Set(),\n): string {\n\tconst lines: string[] = [];\n\tconst end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n\n\tfor (let i = scrollOffset; i < end; i++) {\n\t\tconst item = filtered[i]!;\n\t\tconst isCursor = i === cursor && !addCursor;\n\t\tconst isChecked = selected.has(item.value);\n\n\t\tconst icon = isChecked\n\t\t\t? isCursor\n\t\t\t\t? info(\"◼\")\n\t\t\t\t: info(\"◼\")\n\t\t\t: isCursor\n\t\t\t\t? active(\"◻\")\n\t\t\t\t: dim(\"◻\");\n\n\t\tlet label = item.isCustom ? `${item.label} ${dim(\"(custom)\")}` : item.label;\n\t\tif (isCursor) label = bld(label);\n\n\t\tlines.push(`${info(S_BAR)} ${icon} ${label}`);\n\t}\n\n\t// \"Add pattern\" option\n\tconst trimmed = filter.trim();\n\tconst allItems = [...filtered]; // simplified: just check filtered\n\tconst isNewPattern =\n\t\ttrimmed.length > 0 &&\n\t\t!allItems.some((i) => i.value === trimmed) &&\n\t\t!customPatterns.includes(trimmed);\n\n\tif (isNewPattern) {\n\t\tconst err =\n\t\t\tvalidateBranchPattern(trimmed) ??\n\t\t\t(excludedPatterns.has(trimmed)\n\t\t\t\t? \"Already used for automatic translation\"\n\t\t\t\t: null);\n\t\tconst icon = addCursor ? active(\"◻\") : dim(\"◻\");\n\t\tconst label = err\n\t\t\t? `${ylw(\"+\")} ${dim(`\"${trimmed}\" — ${err}`)}`\n\t\t\t: `${grn(\"+\")} Add \"${trimmed}\" as branch pattern`;\n\t\tlines.push(`${info(S_BAR)} ${icon} ${label}`);\n\t} else if (filtered.length === 0 && trimmed.length === 0) {\n\t\tlines.push(dim(`${S_BAR} No branches detected`));\n\t}\n\n\tconst hidden = filtered.length - (end - scrollOffset);\n\tif (hidden > 0) lines.push(dim(`${S_BAR} ${hidden} more`));\n\tif (selected.size > 0) {\n\t\tlines.push(dim(`${S_BAR} ${selected.size} selected — Enter to confirm`));\n\t} else if (optional) {\n\t\tlines.push(dim(`${S_BAR} Enter to skip`));\n\t}\n\n\treturn lines.join(\"\\n\");\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport async function filterableBranchSelect(params: {\n\tmessage: string;\n\tbranches: string[];\n\tdefaultBranch: string;\n\tinitialValues?: string[];\n\t/** When true, empty selection is accepted (Enter = skip) */\n\toptional?: boolean;\n\t/** Branches already claimed by other trigger types — block custom entry of these */\n\texcludedPatterns?: string[];\n}): Promise<string[] | null> {\n\tconst { message, branches, defaultBranch } = params;\n\tconst optional = params.optional ?? false;\n\tconst excludedSet = new Set(params.excludedPatterns ?? []);\n\n\tlet filter = \"\";\n\tlet cursor = 0;\n\tlet scrollOffset = 0;\n\tlet addCursor = false;\n\tconst customPatterns: string[] = [];\n\tconst selected = new Set<string>(params.initialValues ?? [defaultBranch]);\n\n\tconst getItems = () => buildItems(branches, defaultBranch, customPatterns);\n\tconst getFiltered = () => filterItems(getItems(), filter);\n\n\tconst isNewPattern = () => {\n\t\tconst t = filter.trim();\n\t\tif (!t) return false;\n\t\treturn (\n\t\t\t!getItems().some((i) => i.value === t) && !customPatterns.includes(t)\n\t\t);\n\t};\n\n\tconst clampCursor = (filtered: BranchItem[]) => {\n\t\tconst hasAdd = isNewPattern();\n\t\tconst max = filtered.length - 1 + (hasAdd ? 1 : 0);\n\t\tif (cursor > max && !addCursor) cursor = Math.max(0, max);\n\t\tif (!addCursor) {\n\t\t\tif (cursor < scrollOffset) scrollOffset = cursor;\n\t\t\tif (cursor >= scrollOffset + MAX_VISIBLE)\n\t\t\t\tscrollOffset = cursor - MAX_VISIBLE + 1;\n\t\t\tif (scrollOffset < 0) scrollOffset = 0;\n\t\t}\n\t};\n\n\tconst prompt = new (Prompt as any)(\n\t\t{\n\t\t\tvalidate() {\n\t\t\t\tif (!optional && selected.size === 0)\n\t\t\t\t\treturn \"At least one branch is required.\";\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\trender(this: { state: string; error: string }) {\n\t\t\t\tconst filtered = getFiltered();\n\t\t\t\tclampCursor(filtered);\n\n\t\t\t\tconst hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n\t\t\t\tconst hint =\n\t\t\t\t\tfilter.length > 0\n\t\t\t\t\t\t? filter\n\t\t\t\t\t\t: dim(\"type to filter or add pattern, ↑↓ navigate, space select\");\n\n\t\t\t\tswitch (this.state) {\n\t\t\t\t\tcase \"submit\": {\n\t\t\t\t\t\tconst summary =\n\t\t\t\t\t\t\tselected.size > 0\n\t\t\t\t\t\t\t\t? bld(Array.from(selected).join(\", \"))\n\t\t\t\t\t\t\t\t: dim(\"none\");\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)} ${summary}`;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"cancel\":\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)}`;\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${ylw(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\t\tfilter,\n\t\t\t\t\t\t\t\tcustomPatterns,\n\t\t\t\t\t\t\t\taddCursor,\n\t\t\t\t\t\t\t\toptional,\n\t\t\t\t\t\t\t\texcludedSet,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${ylw(S_BAR_END)} ${ylw(this.error)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${info(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\t\tfilter,\n\t\t\t\t\t\t\t\tcustomPatterns,\n\t\t\t\t\t\t\t\taddCursor,\n\t\t\t\t\t\t\t\toptional,\n\t\t\t\t\t\t\t\texcludedSet,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${info(S_BAR_END)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tfalse,\n\t) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n\tprompt.on(\"key\", (key: string | undefined) => {\n\t\tif (!key || key === \" \") return;\n\t\tconst cp = key.codePointAt(0) ?? 0;\n\t\tif (cp === 0x7f || cp === 0x08) {\n\t\t\tfilter = filter.slice(0, -1);\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t\taddCursor = false;\n\t\t} else if (cp >= 32 && cp !== 127) {\n\t\t\tfilter += key;\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t\taddCursor = false;\n\t\t}\n\t});\n\n\tprompt.on(\"cursor\", (action: string | undefined) => {\n\t\tconst filtered = getFiltered();\n\t\tconst hasAdd = isNewPattern();\n\n\t\tswitch (action) {\n\t\t\tcase \"up\":\n\t\t\t\tif (addCursor) {\n\t\t\t\t\taddCursor = false;\n\t\t\t\t\tcursor = Math.max(0, filtered.length - 1);\n\t\t\t\t} else cursor = Math.max(0, cursor - 1);\n\t\t\t\tbreak;\n\t\t\tcase \"down\":\n\t\t\t\tif (!addCursor && cursor >= filtered.length - 1 && hasAdd)\n\t\t\t\t\taddCursor = true;\n\t\t\t\telse if (!addCursor) cursor = Math.min(filtered.length - 1, cursor + 1);\n\t\t\t\tbreak;\n\t\t\tcase \"space\":\n\t\t\t\tif (addCursor) {\n\t\t\t\t\tconst t = filter.trim();\n\t\t\t\t\tconst err =\n\t\t\t\t\t\tvalidateBranchPattern(t) ??\n\t\t\t\t\t\t(excludedSet.has(t)\n\t\t\t\t\t\t\t? \"Already used for automatic translation\"\n\t\t\t\t\t\t\t: null);\n\t\t\t\t\tif (!err) {\n\t\t\t\t\t\tcustomPatterns.push(t);\n\t\t\t\t\t\tselected.add(t);\n\t\t\t\t\t\tfilter = \"\";\n\t\t\t\t\t\tcursor = 0;\n\t\t\t\t\t\tscrollOffset = 0;\n\t\t\t\t\t\taddCursor = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst item = filtered[cursor];\n\t\t\t\t\tif (item) {\n\t\t\t\t\t\tif (selected.has(item.value)) selected.delete(item.value);\n\t\t\t\t\t\telse selected.add(item.value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tprompt.on(\"finalize\", () => {\n\t\tif ((prompt as any).state === \"submit\") {\n\t\t\t(prompt as any).value = Array.from(selected);\n\t\t}\n\t});\n\n\tconst result = await prompt.prompt();\n\tif (isCancel(result)) return null;\n\treturn result as unknown as string[];\n}\n","import chalk from \"chalk\";\n\nconst ORANGE = \"#FC5206\";\nconst PINK = \"#D51977\";\nconst BLUE = \"#2450A9\";\n\nconst noColor = process.env.NO_COLOR === \"1\" || process.env.FORCE_COLOR === \"0\";\nconst hex = (color: string) => (s: string) =>\n\tnoColor ? s : chalk.hex(color)(s);\n\nexport const dim = (s: string) => (noColor ? s : chalk.dim(s));\nexport const bld = (s: string) => (noColor ? s : chalk.bold(s));\nexport const grn = (s: string) => (noColor ? s : chalk.green(s));\nexport const ylw = (s: string) => (noColor ? s : chalk.yellow(s));\nexport const red = (s: string) => (noColor ? s : chalk.red(s));\n\n/** Named values: file paths, locale codes, branch names, variable names */\nexport const highlight = hex(PINK);\n\n/** Structural info: bars, info logs, notes, links, selected checkmarks */\nexport const info = hex(BLUE);\n\n/** Brand identity: intro/outro text, active cursor ◆, spinner label accents */\nexport const active = hex(ORANGE);\n","import { isCancel, Prompt } from \"@clack/core\";\nimport * as p from \"@clack/prompts\";\nimport { active, bld, dim, grn, info, red, ylw } from \"./theme.js\";\n\nexport interface LocaleOption {\n\tbcp47: string;\n\t/** Human-readable label, e.g. \"English — en\" */\n\tlabel: string;\n}\n\n// ── Symbols (match @clack/prompts style) ──────────────────────────────────────\n\nconst S_BAR = \"│\";\nconst S_BAR_END = \"└\";\nconst S_ACTIVE = \"◆\";\nconst S_SUBMIT = \"◆\";\nconst S_CANCEL = \"■\";\nconst S_ERROR = \"▲\";\n\nfunction symbol(state: string): string {\n\tswitch (state) {\n\t\tcase \"submit\":\n\t\t\treturn grn(S_SUBMIT);\n\t\tcase \"cancel\":\n\t\t\treturn red(S_CANCEL);\n\t\tcase \"error\":\n\t\t\treturn ylw(S_ERROR);\n\t\tdefault:\n\t\t\treturn active(S_ACTIVE);\n\t}\n}\n\n// ── Filter ────────────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 12;\n\nfunction filterLocales(options: LocaleOption[], query: string): LocaleOption[] {\n\tif (!query.trim()) return options;\n\tconst lower = query.toLowerCase();\n\treturn options.filter(\n\t\t(o) =>\n\t\t\to.bcp47.toLowerCase().includes(lower) ||\n\t\t\to.label.toLowerCase().includes(lower),\n\t);\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nfunction buildList(\n\tfiltered: LocaleOption[],\n\tcursor: number,\n\tscrollOffset: number,\n\tselected: Set<string> | null, // null = single-select\n): string {\n\tconst isMulti = selected !== null;\n\tconst end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n\tconst visibleLines: string[] = [];\n\n\tfor (let i = scrollOffset; i < end; i++) {\n\t\tconst opt = filtered[i]!;\n\t\tconst isCursor = i === cursor;\n\t\tconst isChecked = isMulti && selected!.has(opt.bcp47);\n\n\t\tconst icon = isMulti\n\t\t\t? isChecked\n\t\t\t\t? isCursor\n\t\t\t\t\t? info(\"◼\")\n\t\t\t\t\t: info(\"◼\")\n\t\t\t\t: isCursor\n\t\t\t\t\t? active(\"◻\")\n\t\t\t\t\t: dim(\"◻\")\n\t\t\t: isCursor\n\t\t\t\t? active(\"●\")\n\t\t\t\t: dim(\"○\");\n\n\t\tvisibleLines.push(\n\t\t\t`${info(S_BAR)} ${icon} ${isCursor ? bld(opt.label) : opt.label}`,\n\t\t);\n\t}\n\n\tconst hidden = filtered.length - (end - scrollOffset);\n\tif (hidden > 0)\n\t\tvisibleLines.push(dim(`${S_BAR} ${hidden} more — keep typing to narrow`));\n\tif (filtered.length === 0) visibleLines.push(dim(`${S_BAR} No matches`));\n\tif (isMulti && selected!.size > 0) {\n\t\tvisibleLines.push(\n\t\t\tdim(`${S_BAR} ${selected!.size} selected — Enter to confirm`),\n\t\t);\n\t}\n\n\treturn visibleLines.join(\"\\n\");\n}\n\n// ── Core prompt factory ───────────────────────────────────────────────────────\n\nasync function runFilterablePrompt(opts: {\n\tmessage: string;\n\toptions: LocaleOption[];\n\tmulti: boolean;\n\tinitialValue?: string;\n\tinitialValues?: string[];\n}): Promise<string | string[] | null> {\n\tconst { message, options, multi } = opts;\n\n\tlet filter = \"\";\n\tlet cursor = 0;\n\tlet scrollOffset = 0;\n\tconst selected = new Set<string>(multi ? (opts.initialValues ?? []) : []);\n\n\tif (!multi && opts.initialValue) {\n\t\tconst idx = options.findIndex((o) => o.bcp47 === opts.initialValue);\n\t\tif (idx >= 0) cursor = idx;\n\t}\n\n\tconst getFiltered = () => filterLocales(options, filter);\n\n\t// Keep cursor in bounds and scroll window centred\n\tconst clampCursor = (filtered: LocaleOption[]) => {\n\t\tif (cursor >= filtered.length) cursor = Math.max(0, filtered.length - 1);\n\t\tif (cursor < scrollOffset) scrollOffset = cursor;\n\t\tif (cursor >= scrollOffset + MAX_VISIBLE)\n\t\t\tscrollOffset = cursor - MAX_VISIBLE + 1;\n\t\tif (scrollOffset < 0) scrollOffset = 0;\n\t};\n\n\t// @clack/core Prompt: render() returns the ENTIRE frame; clack handles\n\t// re-rendering (cursor movement + diff) automatically.\n\t// Using `any` cast to pass `trackValue=false` (2nd constructor arg).\n\tconst prompt = new (Prompt as any)(\n\t\t{\n\t\t\tinitialValue: !multi ? (options[cursor]?.bcp47 ?? null) : null,\n\t\t\tvalidate() {\n\t\t\t\tconst f = getFiltered();\n\t\t\t\tif (multi && selected.size === 0)\n\t\t\t\t\treturn \"At least one target language is required.\";\n\t\t\t\tif (!multi && !f[cursor]) return \"Please select a language.\";\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\trender(this: { state: string; error: string; value: unknown }) {\n\t\t\t\tconst filtered = getFiltered();\n\t\t\t\tclampCursor(filtered);\n\n\t\t\t\tconst hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n\t\t\t\tconst hint =\n\t\t\t\t\tfilter.length > 0\n\t\t\t\t\t\t? filter\n\t\t\t\t\t\t: dim(\n\t\t\t\t\t\t\t\t`type to filter, ↑↓ navigate${multi ? \", space select\" : \"\"}`,\n\t\t\t\t\t\t\t);\n\n\t\t\t\tswitch (this.state) {\n\t\t\t\t\tcase \"submit\": {\n\t\t\t\t\t\tconst val = multi\n\t\t\t\t\t\t\t? Array.from(selected)\n\t\t\t\t\t\t\t\t\t.map((id) => options.find((o) => o.bcp47 === id)?.label ?? id)\n\t\t\t\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\t\t\t: (options.find((o) => o.bcp47 === (this.value as string))\n\t\t\t\t\t\t\t\t\t?.label ?? \"\");\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)} ${bld(val || dim(\"none\"))}`;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"cancel\":\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)}`;\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${ylw(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tmulti ? selected : null,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${ylw(S_BAR_END)} ${ylw(this.error)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${info(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tmulti ? selected : null,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${info(S_BAR_END)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tfalse, // trackValue=false — we manage value manually\n\t) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n\t// Character input → update filter\n\tprompt.on(\"key\", (key: string | undefined) => {\n\t\tif (!key || key === \" \") return; // space handled by cursor event\n\t\tconst cp = key.codePointAt(0) ?? 0;\n\t\tif (cp === 0x7f || cp === 0x08) {\n\t\t\t// backspace\n\t\t\tfilter = filter.slice(0, -1);\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t} else if (cp >= 32 && cp !== 127) {\n\t\t\tfilter += key;\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t}\n\t});\n\n\t// Navigation + toggle\n\tprompt.on(\"cursor\", (action: string | undefined) => {\n\t\tconst filtered = getFiltered();\n\t\tswitch (action) {\n\t\t\tcase \"up\":\n\t\t\t\tcursor = Math.max(0, cursor - 1);\n\t\t\t\tbreak;\n\t\t\tcase \"down\":\n\t\t\t\tcursor = Math.min(Math.max(filtered.length - 1, 0), cursor + 1);\n\t\t\t\tbreak;\n\t\t\tcase \"space\":\n\t\t\t\tif (multi) {\n\t\t\t\t\tconst opt = filtered[cursor];\n\t\t\t\t\tif (opt) {\n\t\t\t\t\t\tif (selected.has(opt.bcp47)) selected.delete(opt.bcp47);\n\t\t\t\t\t\telse selected.add(opt.bcp47);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\t// Sync prompt.value for single-select so submit gets the right value\n\t\tif (!multi) {\n\t\t\tconst opt = getFiltered()[cursor];\n\t\t\t(prompt as any).value = opt?.bcp47 ?? null;\n\t\t}\n\t});\n\n\t// Before submit resolves, set value to the selected items (multi) or current cursor (single)\n\tprompt.on(\"finalize\", () => {\n\t\tif ((prompt as any).state === \"submit\") {\n\t\t\tif (multi) {\n\t\t\t\t(prompt as any).value = Array.from(selected);\n\t\t\t} else {\n\t\t\t\tconst f = getFiltered();\n\t\t\t\t(prompt as any).value = f[cursor]?.bcp47 ?? null;\n\t\t\t}\n\t\t}\n\t});\n\n\tconst result = await prompt.prompt();\n\n\tif (isCancel(result)) return null;\n\treturn result as string | string[];\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport async function searchSelectLocale(\n\toptions: LocaleOption[],\n\tmessage: string,\n\tinitialValue?: string,\n): Promise<string | null> {\n\tconst result = await runFilterablePrompt({\n\t\tmessage,\n\t\toptions,\n\t\tmulti: false,\n\t\tinitialValue,\n\t});\n\treturn typeof result === \"string\" ? result : null;\n}\n\nexport async function searchMultiSelectLocales(\n\toptions: LocaleOption[],\n\tmessage: string,\n\tinitialValues?: string[],\n): Promise<string[] | null> {\n\tconst result = await runFilterablePrompt({\n\t\tmessage,\n\t\toptions,\n\t\tmulti: true,\n\t\tinitialValues,\n\t});\n\tif (result === null) return null;\n\tconst picks = result as string[];\n\t// Validate already prevents empty on first try; this handles the retry path\n\tif (picks.length === 0) {\n\t\tp.log.warn(\n\t\t\t\"At least one target language is required. Please select at least one.\",\n\t\t);\n\t\treturn searchMultiSelectLocales(options, message, initialValues);\n\t}\n\treturn picks;\n}\n","import { execSync } from \"node:child_process\";\nimport { relative, resolve } from \"node:path\";\n\nexport type GitRepositoryIdentity = {\n\trepoCanonical: string;\n\trepoAppDir: string;\n};\n\nexport type GitContext = {\n\tidentity: GitRepositoryIdentity | null;\n\twarnings: string[];\n};\n\nconst SHA_REGEX = /^[0-9a-f]{40}$/i;\n\n/**\n * Detect the current commit SHA from CI env vars or git.\n * Must produce the same result as detectCommitSha() in @vocoder/plugin\n * so fingerprints computed by CLI sync and unplugin build match.\n */\nexport function detectCommitSha(): string | null {\n\tif (\n\t\tprocess.env.VOCODER_COMMIT_SHA &&\n\t\tSHA_REGEX.test(process.env.VOCODER_COMMIT_SHA)\n\t) {\n\t\treturn process.env.VOCODER_COMMIT_SHA;\n\t}\n\n\tconst knownSha =\n\t\tprocess.env.GITHUB_SHA ||\n\t\tprocess.env.VERCEL_GIT_COMMIT_SHA ||\n\t\tprocess.env.CI_COMMIT_SHA ||\n\t\tprocess.env.BITBUCKET_COMMIT ||\n\t\tprocess.env.CIRCLE_SHA1 ||\n\t\tprocess.env.RENDER_GIT_COMMIT;\n\n\tif (knownSha && SHA_REGEX.test(knownSha)) return knownSha;\n\n\treturn safeExec(\"git rev-parse HEAD\");\n}\n\nfunction safeExec(command: string): string | null {\n\ttry {\n\t\tconst output = execSync(command, {\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t}).trim();\n\t\treturn output.length > 0 ? output : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction normalizePath(pathname: string): string | null {\n\tconst cleaned = pathname\n\t\t.replace(/^\\/+/, \"\")\n\t\t.replace(/\\.git$/i, \"\")\n\t\t.trim();\n\n\tif (!cleaned || !cleaned.includes(\"/\")) {\n\t\treturn null;\n\t}\n\n\treturn cleaned;\n}\n\nfunction parseRemoteUrl(remoteUrl: string): {\n\thost: string;\n\townerRepoPath: string;\n} | null {\n\tconst trimmed = remoteUrl.trim();\n\tif (!trimmed) {\n\t\treturn null;\n\t}\n\n\t// SCP-like syntax: git@github.com:owner/repo.git\n\tif (!trimmed.includes(\"://\")) {\n\t\tconst scpMatch = trimmed.match(/^(?:.+@)?([^:]+):(.+)$/);\n\t\tif (scpMatch) {\n\t\t\tconst host = (scpMatch[1] || \"\").toLowerCase();\n\t\t\tconst ownerRepoPath = normalizePath(scpMatch[2] || \"\");\n\t\t\tif (!host || !ownerRepoPath) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn { host, ownerRepoPath };\n\t\t}\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst parsed = new URL(trimmed);\n\t\tconst host = parsed.hostname.toLowerCase();\n\t\tconst ownerRepoPath = normalizePath(decodeURIComponent(parsed.pathname));\n\t\tif (!host || !ownerRepoPath) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { host, ownerRepoPath };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction toCanonical(host: string, ownerRepoPath: string): string {\n\tif (host.includes(\"github.com\")) {\n\t\treturn `github:${ownerRepoPath.toLowerCase()}`;\n\t}\n\tif (host.includes(\"gitlab.com\")) {\n\t\treturn `gitlab:${ownerRepoPath.toLowerCase()}`;\n\t}\n\tif (host.includes(\"bitbucket.org\")) {\n\t\treturn `bitbucket:${ownerRepoPath.toLowerCase()}`;\n\t}\n\treturn `git:${host}/${ownerRepoPath.toLowerCase()}`;\n}\n\nexport function resolveGitRepositoryIdentity(): GitRepositoryIdentity | null {\n\tconst remoteUrl = safeExec(\"git config --get remote.origin.url\");\n\tif (!remoteUrl) {\n\t\treturn null;\n\t}\n\n\tconst parsed = parseRemoteUrl(remoteUrl);\n\tif (!parsed) {\n\t\treturn null;\n\t}\n\n\tconst repositoryRoot = safeExec(\"git rev-parse --show-toplevel\");\n\tconst currentDirectory = process.cwd();\n\tlet repoAppDir = \"\";\n\tif (repositoryRoot) {\n\t\tconst relativePath = relative(\n\t\t\tresolve(repositoryRoot),\n\t\t\tresolve(currentDirectory),\n\t\t)\n\t\t\t.replace(/\\\\/g, \"/\")\n\t\t\t.trim();\n\n\t\tif (\n\t\t\trelativePath &&\n\t\t\trelativePath !== \".\" &&\n\t\t\t!relativePath.startsWith(\"..\")\n\t\t) {\n\t\t\trepoAppDir = relativePath;\n\t\t}\n\t}\n\n\treturn {\n\t\trepoCanonical: toCanonical(parsed.host, parsed.ownerRepoPath),\n\t\trepoAppDir,\n\t};\n}\n\nexport function resolveGitContext(): GitContext {\n\tconst warnings: string[] = [];\n\tconst identity = resolveGitRepositoryIdentity();\n\n\tif (!identity) {\n\t\twarnings.push(\n\t\t\t\"Could not detect git remote origin. Repo binding will be skipped until sync can detect it.\",\n\t\t);\n\t}\n\n\treturn { identity, warnings };\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\n\nexport interface WorkspaceInfo {\n\tid: string;\n\tname: string;\n\tplanId: string;\n\tprojectCount: number;\n\thasGitHubConnection: boolean;\n\tconnectionLabel: string | null;\n}\n\nexport interface WorkspaceListResult {\n\tworkspaces: WorkspaceInfo[];\n\tcanCreateWorkspace: boolean;\n}\n\nexport type WorkspaceSelection =\n\t| { action: \"use\"; workspace: WorkspaceInfo }\n\t| { action: \"create\" }\n\t| { action: \"cancelled\" };\n\nfunction _workspaceLabel(ws: WorkspaceInfo): string {\n\tconst parts: string[] = [ws.name];\n\tconst meta: string[] = [];\n\n\tif (ws.projectCount === 1) {\n\t\tmeta.push(\"1 project\");\n\t} else if (ws.projectCount > 1) {\n\t\tmeta.push(`${ws.projectCount} projects`);\n\t}\n\n\tif (ws.connectionLabel) {\n\t\tmeta.push(`GitHub: ${ws.connectionLabel}`);\n\t}\n\n\tif (meta.length > 0) {\n\t\tparts.push(chalk.dim(`(${meta.join(\", \")})`));\n\t}\n\n\treturn parts.join(\" \");\n}\n\n/**\n * Prompt the user to select a workspace or create a new one.\n * Returns a `WorkspaceSelection` describing what the user chose.\n */\nexport async function selectWorkspace(\n\tresult: WorkspaceListResult,\n): Promise<WorkspaceSelection> {\n\tconst { workspaces, canCreateWorkspace } = result;\n\n\tif (workspaces.length === 0) {\n\t\t// No workspaces — must create\n\t\treturn { action: \"create\" };\n\t}\n\n\ttype SelectValue = string | \"create\";\n\n\tconst options: Array<{ value: SelectValue; label: string; hint?: string }> =\n\t\tworkspaces.map((ws) => ({\n\t\t\tvalue: ws.id,\n\t\t\tlabel: ws.name,\n\t\t\thint:\n\t\t\t\t[\n\t\t\t\t\tws.projectCount > 0\n\t\t\t\t\t\t? `${ws.projectCount} project${ws.projectCount !== 1 ? \"s\" : \"\"}`\n\t\t\t\t\t\t: \"\",\n\t\t\t\t\tws.connectionLabel ? `GitHub: ${ws.connectionLabel}` : \"\",\n\t\t\t\t]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join(\" · \") || undefined,\n\t\t}));\n\n\tif (canCreateWorkspace) {\n\t\toptions.push({ value: \"create\", label: \"Create new workspace\" });\n\t}\n\n\tconst selected = await p.select<SelectValue>({\n\t\tmessage: \"Select workspace\",\n\t\toptions,\n\t});\n\n\tif (p.isCancel(selected)) {\n\t\treturn { action: \"cancelled\" };\n\t}\n\n\tif (selected === \"create\") {\n\t\treturn { action: \"create\" };\n\t}\n\n\tconst workspace = workspaces.find((ws) => ws.id === selected);\n\tif (!workspace) {\n\t\treturn { action: \"cancelled\" };\n\t}\n\n\treturn { action: \"use\", workspace };\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport { getLimitErrorGuidance } from \"./sync.js\";\n\nloadEnv();\n\nexport interface LocaleCommandOptions {\n\tapiUrl?: string;\n}\n\nfunction getApiConfig(options: LocaleCommandOptions): {\n\tapiKey: string;\n\tapiUrl: string;\n} | null {\n\tconst apiKey = process.env.VOCODER_API_KEY;\n\tif (!apiKey) {\n\t\tp.log.error(\n\t\t\t\"VOCODER_API_KEY is not set. Run `npx @vocoder/cli init` to set up your project.\",\n\t\t);\n\t\treturn null;\n\t}\n\treturn {\n\t\tapiKey,\n\t\tapiUrl: options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\",\n\t};\n}\n\n/**\n * Lists the project's configured source locale and target locales.\n * Reads the project API key from VOCODER_API_KEY.\n *\n * Endpoint: GET /api/cli/config\n *\n * @throws If VOCODER_API_KEY is missing or the API call fails.\n */\nexport async function listProjectLocales(options: LocaleCommandOptions = {}): Promise<number> {\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\n\ttry {\n\t\tconst projectConfig = await api.getAppConfig();\n\n\t\tp.log.info(\n\t\t\t`Source locale: ${highlight(projectConfig.sourceLocale)}`,\n\t\t);\n\n\t\tif (projectConfig.targetLocales.length === 0) {\n\t\t\tp.log.info(\"Target locales: (none configured)\");\n\t\t} else {\n\t\t\tp.log.info(\n\t\t\t\t`Target locales: ${projectConfig.targetLocales.map((l) => highlight(l)).join(\", \")}`,\n\t\t\t);\n\t\t}\n\n\t\treturn 0;\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to fetch project locales.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n\n/**\n * Adds one or more target locales to the project.\n * Loops per locale — the API accepts one locale at a time.\n * Idempotent: locales already configured are silently skipped.\n *\n * Endpoint: POST /api/cli/project/locales (one call per locale)\n *\n * @param locales Array of BCP 47 locale codes to add, e.g. [\"fr\", \"de\", \"pt-BR\"].\n * @throws {VocoderAPIError} status 422 for invalid/unsupported locale code.\n * @throws {VocoderAPIError} status 403 when the plan's maxTargetLocalesPerProject limit is reached.\n */\nexport async function addLocales(\n\tlocales: string[],\n\toptions: LocaleCommandOptions = {},\n): Promise<number> {\n\tif (locales.length === 0) {\n\t\tp.log.error(\"No locale codes provided.\");\n\t\treturn 1;\n\t}\n\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\tlet lastTargetLocales: string[] = [];\n\tlet hadError = false;\n\n\tfor (const locale of locales) {\n\t\tconst spinner = p.spinner();\n\t\tspinner.start(`Adding ${locale}…`);\n\n\t\ttry {\n\t\t\tconst result = await api.addLocale(locale);\n\t\t\tlastTargetLocales = result.targetLocales;\n\t\t\tspinner.stop(`Added ${highlight(locale)}`);\n\t\t} catch (error) {\n\t\t\tspinner.stop(`Failed to add ${chalk.red(locale)}`);\n\t\t\thadError = true;\n\n\t\t\tif (error instanceof VocoderAPIError && error.limitError) {\n\t\t\t\tconst { limitError } = error;\n\t\t\t\tp.log.error(limitError.message);\n\t\t\t\tfor (const line of getLimitErrorGuidance(limitError)) {\n\t\t\t\t\tp.log.info(line);\n\t\t\t\t}\n\t\t\t\t// Plan limit hit — remaining locales will also fail, so stop early\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tp.log.error(\n\t\t\t\terror instanceof Error ? error.message : \"Unknown error\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastTargetLocales.length > 0) {\n\t\tp.log.info(\n\t\t\t`Target locales now: ${lastTargetLocales.map((l) => highlight(l)).join(\", \")}`,\n\t\t);\n\t}\n\n\treturn hadError ? 1 : 0;\n}\n\n/**\n * Removes one or more target locales from the project.\n * Loops per locale — the API accepts one locale at a time.\n * Idempotent: locales not currently configured are silently skipped.\n *\n * Endpoint: DELETE /api/cli/project/locales (one call per locale)\n *\n * @param locales Array of BCP 47 locale codes to remove, e.g. [\"fr\", \"de\"].\n */\nexport async function removeLocales(\n\tlocales: string[],\n\toptions: LocaleCommandOptions = {},\n): Promise<number> {\n\tif (locales.length === 0) {\n\t\tp.log.error(\"No locale codes provided.\");\n\t\treturn 1;\n\t}\n\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\tlet lastTargetLocales: string[] = [];\n\tlet hadError = false;\n\n\tfor (const locale of locales) {\n\t\tconst spinner = p.spinner();\n\t\tspinner.start(`Removing ${locale}…`);\n\n\t\ttry {\n\t\t\tconst result = await api.removeLocale(locale);\n\t\t\tlastTargetLocales = result.targetLocales;\n\t\t\tspinner.stop(`Removed ${highlight(locale)}`);\n\t\t} catch (error) {\n\t\t\tspinner.stop(`Failed to remove ${chalk.red(locale)}`);\n\t\t\thadError = true;\n\t\t\tp.log.error(\n\t\t\t\terror instanceof Error ? error.message : \"Unknown error\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastTargetLocales.length > 0) {\n\t\tp.log.info(\n\t\t\t`Target locales now: ${lastTargetLocales.map((l) => highlight(l)).join(\", \")}`,\n\t\t);\n\t} else if (!hadError) {\n\t\tp.log.info(\"Target locales now: (none configured)\");\n\t}\n\n\treturn hadError ? 1 : 0;\n}\n\n/**\n * Lists all locales supported by Vocoder.\n * Useful for discovering valid BCP 47 codes before calling `add`.\n *\n * Endpoint: GET /api/cli/locales (accepts both user tokens and project API keys)\n */\nexport async function listSupportedLocales(options: LocaleCommandOptions = {}): Promise<number> {\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\n\ttry {\n\t\t// GET /api/cli/locales accepts both user tokens and project API keys as Bearer tokens\n\t\tconst result = await api.listLocales(config.apiKey);\n\t\tp.log.info(chalk.bold(\"Source locales:\"));\n\t\tprintLocaleTable(result.sourceLocales);\n\t\tp.log.info(\"\");\n\t\tp.log.info(chalk.bold(\"Target locales:\"));\n\t\tprintLocaleTable(result.targetLocales);\n\t\treturn 0;\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to fetch supported locales.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n\nfunction printLocaleTable(\n\tlocales: Array<{ code: string; name: string; nativeName?: string }>,\n): void {\n\tfor (const locale of locales) {\n\t\tconst native =\n\t\t\tlocale.nativeName && locale.nativeName !== locale.name\n\t\t\t\t? ` (${locale.nativeName})`\n\t\t\t\t: \"\";\n\t\tp.log.info(` ${highlight(locale.code.padEnd(10))} ${locale.name}${native}`);\n\t}\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { highlight } from \"../utils/theme.js\";\nimport type { VocoderTranslationData } from \"@vocoder/config\";\nimport { loadVocoderConfig } from \"@vocoder/extractor\";\nimport type {\n\tEffectiveSyncMode,\n\tExtractedString,\n\tLimitErrorResponse,\n\tLocalesMap,\n\tProjectConfig,\n\tRequestedSyncMode,\n\tSyncPolicyConfig,\n\tTranslateOptions,\n\tTranslationStringEntry,\n} from \"../types.js\";\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport { detectBranch, isTargetBranch } from \"../utils/branch.js\";\nimport { getMergedConfig, validateLocalConfig } from \"../utils/config.js\";\nimport { StringExtractor } from \"../utils/extract.js\";\nimport {\n\tdetectCommitSha,\n\tresolveGitRepositoryIdentity,\n} from \"../utils/git-identity.js\";\n\ntype LocaleMetadataMap = LocalesMap;\ntype TranslationMap = Record<string, Record<string, string>>;\ntype TranslationArtifactSource = \"fresh\" | \"local-cache\" | \"api-snapshot\";\n\ntype TranslationArtifacts = {\n\tsource: TranslationArtifactSource;\n\ttranslations: TranslationMap;\n\tlocaleMetadata?: LocaleMetadataMap;\n\tsnapshotBatchId?: string;\n\tcompletedAt?: string | null;\n};\n\nfunction computeFingerprint(shortCode: string, texts: string[]): string {\n\tconst sorted = [...texts].sort();\n\treturn createHash(\"sha256\")\n\t\t.update(`${shortCode}:${sorted.join(\"\\0\")}`)\n\t\t.digest(\"hex\")\n\t\t.slice(0, 12);\n}\n\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseLocaleMetadata(value: unknown): LocaleMetadataMap | undefined {\n\tif (!isRecord(value)) {\n\t\treturn undefined;\n\t}\n\n\tconst metadata: LocaleMetadataMap = {};\n\tfor (const [locale, rawValue] of Object.entries(value)) {\n\t\tif (!isRecord(rawValue)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nativeName = rawValue.nativeName;\n\t\tif (typeof nativeName !== \"string\" || nativeName.trim().length === 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entry: { nativeName: string; dir?: \"rtl\" } = { nativeName };\n\t\tif (rawValue.dir === \"rtl\") {\n\t\t\tentry.dir = \"rtl\";\n\t\t}\n\n\t\tmetadata[locale] = entry;\n\t}\n\n\treturn Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction parseTranslations(value: unknown): TranslationMap | null {\n\tif (!isRecord(value)) {\n\t\treturn null;\n\t}\n\n\tconst translations: TranslationMap = {};\n\n\tfor (const [locale, localeValue] of Object.entries(value)) {\n\t\tif (!isRecord(localeValue)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst localeTranslations: Record<string, string> = {};\n\t\tfor (const [source, translated] of Object.entries(localeValue)) {\n\t\t\tif (typeof translated === \"string\") {\n\t\t\t\tlocaleTranslations[source] = translated;\n\t\t\t}\n\t\t}\n\n\t\ttranslations[locale] = localeTranslations;\n\t}\n\n\treturn Object.keys(translations).length > 0 ? translations : null;\n}\n\nfunction getCacheFilePath(projectRoot: string, fingerprint: string): string {\n\treturn join(projectRoot, \"node_modules\", \".vocoder\", \"cache\", `${fingerprint}.json`);\n}\n\nfunction buildTranslationData(params: {\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\tstringEntries: TranslationStringEntry[];\n\ttranslations: TranslationMap;\n\tlocaleMetadata?: LocaleMetadataMap;\n\tupdatedAt: string;\n}): VocoderTranslationData {\n\t// Remap text-keyed translations → hash-keyed using the string entries the CLI already has\n\tconst textToHash = new Map(params.stringEntries.map((e) => [e.text, e.key]));\n\tconst hashKeyed: TranslationMap = {};\n\tfor (const [locale, localeMap] of Object.entries(params.translations)) {\n\t\thashKeyed[locale] = {};\n\t\tfor (const [text, translation] of Object.entries(localeMap)) {\n\t\t\tconst hash = textToHash.get(text);\n\t\t\tif (hash) hashKeyed[locale][hash] = translation;\n\t\t}\n\t}\n\n\tconst locales: Record<string, { nativeName: string; dir?: \"rtl\" }> = {};\n\tfor (const code of [params.sourceLocale, ...params.targetLocales]) {\n\t\tconst meta = params.localeMetadata?.[code];\n\t\tif (meta) locales[code] = { nativeName: meta.nativeName, ...(meta.dir ? { dir: meta.dir } : {}) };\n\t}\n\n\treturn {\n\t\tconfig: { sourceLocale: params.sourceLocale, targetLocales: params.targetLocales, locales },\n\t\ttranslations: hashKeyed,\n\t\tupdatedAt: params.updatedAt,\n\t};\n}\n\nfunction readLocalCache(params: {\n\tprojectRoot: string;\n\tfingerprint: string;\n}): TranslationArtifacts | null {\n\tconst cacheFilePath = getCacheFilePath(params.projectRoot, params.fingerprint);\n\tif (!existsSync(cacheFilePath)) return null;\n\ttry {\n\t\tconst raw = readFileSync(cacheFilePath, \"utf-8\");\n\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\tif (!isRecord(parsed)) return null;\n\t\t// VocoderTranslationData shape: { config, translations, updatedAt }\n\t\tconst inner = isRecord(parsed.config) ? parsed : null;\n\t\tif (!inner) return null;\n\t\tconst translations = parseTranslations(inner.translations);\n\t\tif (!translations) return null;\n\t\tconst localeMetadata = isRecord(inner.config)\n\t\t\t? parseLocaleMetadata(inner.config.locales)\n\t\t\t: undefined;\n\t\treturn { source: \"local-cache\", translations, localeMetadata };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction writeCache(params: {\n\tprojectRoot: string;\n\tfingerprint: string;\n\tdata: VocoderTranslationData;\n}): string {\n\tconst cacheDir = join(params.projectRoot, \"node_modules\", \".vocoder\", \"cache\");\n\tmkdirSync(cacheDir, { recursive: true });\n\tconst cacheFilePath = getCacheFilePath(params.projectRoot, params.fingerprint);\n\twriteFileSync(cacheFilePath, JSON.stringify(params.data), \"utf-8\");\n\treturn cacheFilePath;\n}\n\nfunction resolveEffectiveModeFromPolicy(params: {\n\tbranch: string;\n\trequestedMode: RequestedSyncMode;\n\tpolicy: SyncPolicyConfig;\n}): EffectiveSyncMode {\n\tconst { requestedMode, policy, branch } = params;\n\n\tlet mode: EffectiveSyncMode;\n\tif (requestedMode === \"auto\") {\n\t\tconst isBlockingBranch = isTargetBranch(branch, policy.blockingBranches);\n\t\tmode = isBlockingBranch ? policy.blockingMode : policy.nonBlockingMode;\n\t} else {\n\t\tmode = requestedMode;\n\t}\n\n\treturn mode;\n}\n\nfunction resolveWaitTimeoutMs(params: {\n\trequestedMaxWaitMs?: number;\n\tpolicyDefaultMaxWaitMs?: number;\n\tfallbackTimeoutMs: number;\n}): number {\n\tif (\n\t\ttypeof params.requestedMaxWaitMs === \"number\" &&\n\t\tNumber.isFinite(params.requestedMaxWaitMs) &&\n\t\tparams.requestedMaxWaitMs > 0\n\t) {\n\t\treturn Math.floor(params.requestedMaxWaitMs);\n\t}\n\n\tif (\n\t\ttypeof params.policyDefaultMaxWaitMs === \"number\" &&\n\t\tNumber.isFinite(params.policyDefaultMaxWaitMs) &&\n\t\tparams.policyDefaultMaxWaitMs > 0\n\t) {\n\t\treturn Math.floor(params.policyDefaultMaxWaitMs);\n\t}\n\n\treturn params.fallbackTimeoutMs;\n}\n\nfunction normalizeTranslations(params: {\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\tsourceStrings: string[];\n\ttranslations: TranslationMap;\n}): TranslationMap {\n\tconst merged: TranslationMap = {};\n\n\tfor (const [locale, values] of Object.entries(params.translations)) {\n\t\tmerged[locale] = { ...values };\n\t}\n\n\tconst expectedLocales = [\n\t\tparams.sourceLocale,\n\t\t...params.targetLocales.filter((locale) => locale !== params.sourceLocale),\n\t];\n\n\tfor (const locale of expectedLocales) {\n\t\tif (!merged[locale]) {\n\t\t\tmerged[locale] = {};\n\t\t}\n\t}\n\n\tif (!merged[params.sourceLocale]) {\n\t\tmerged[params.sourceLocale] = {};\n\t}\n\n\tfor (const sourceText of params.sourceStrings) {\n\t\tif (!(sourceText in merged[params.sourceLocale]!)) {\n\t\t\tmerged[params.sourceLocale]![sourceText] = sourceText;\n\t\t}\n\t}\n\n\treturn merged;\n}\n\nexport function getLimitErrorGuidance(\n\tlimitError: LimitErrorResponse,\n): string[] {\n\tif (limitError.limitType === \"providers\") {\n\t\treturn [\n\t\t\t\"Provider setup required.\",\n\t\t\t\"Add a DeepL API key in Dashboard -> Workspace Settings -> Providers.\",\n\t\t\t`Open settings: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\tif (limitError.limitType === \"translation_chars\") {\n\t\treturn [\n\t\t\t\"Monthly translation character limit reached.\",\n\t\t\t`Used this month: ${limitError.current.toLocaleString()} chars`,\n\t\t\t`Requested after sync: ${limitError.required.toLocaleString()} chars`,\n\t\t\t`Upgrade plan: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\tif (limitError.limitType === \"source_strings\") {\n\t\treturn [\n\t\t\t\"Active source string limit reached.\",\n\t\t\t`Current active strings: ${limitError.current.toLocaleString()}`,\n\t\t\t`Required for this sync: ${limitError.required.toLocaleString()}`,\n\t\t\t`Upgrade plan: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\tif (limitError.limitType === \"target_locales\") {\n\t\treturn [\n\t\t\t`Current target locales: ${limitError.current}`,\n\t\t\t`Plan limit: ${limitError.current} (${limitError.planId})`,\n\t\t\t`Upgrade plan: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\treturn [\n\t\t`Plan: ${limitError.planId}`,\n\t\t`Current: ${limitError.current}`,\n\t\t`Required: ${limitError.required}`,\n\t\t`Upgrade: ${limitError.upgradeUrl}`,\n\t];\n}\n\nfunction getSyncPolicyErrorGuidance(\n\terror: NonNullable<VocoderAPIError[\"syncPolicyError\"]>,\n): string[] {\n\tif (error.errorCode === \"BRANCH_NOT_ALLOWED\") {\n\t\tconst lines = [\"This branch is not allowed for this project.\"];\n\t\tif (error.branch) {\n\t\t\tlines.push(`Current branch: ${error.branch}`);\n\t\t}\n\t\t// targetBranches removed — configure branches in project settings\n\t\tlines.push(\n\t\t\t\"Update your project target branches in the dashboard if needed.\",\n\t\t);\n\t\treturn lines;\n\t}\n\n\tconst lines = [\"This project is bound to a different repository.\"];\n\tif (error.boundRepoLabel) {\n\t\tlines.push(`Bound repository: ${error.boundRepoLabel}`);\n\t}\n\tif (error.boundScopePath) {\n\t\tlines.push(`Bound scope: ${error.boundScopePath}`);\n\t}\n\tlines.push(\n\t\t\"Run `vocoder init` from the correct repository or create a separate project.\",\n\t);\n\treturn lines;\n}\n\nfunction mergeContext(\n\tcurrent: string | undefined,\n\tincoming: string | undefined,\n): string | undefined {\n\tif (!incoming) return current;\n\tif (!current) return incoming;\n\tif (current === incoming) return current;\n\n\tconst merged = new Set(\n\t\t[...current.split(\" | \"), ...incoming.split(\" | \")]\n\t\t\t.map((part) => part.trim())\n\t\t\t.filter(Boolean),\n\t);\n\treturn Array.from(merged).join(\" | \");\n}\n\nfunction buildStringEntries(\n\textractedStrings: ExtractedString[],\n): TranslationStringEntry[] {\n\tconst byText = new Map<string, TranslationStringEntry>();\n\n\tfor (const str of extractedStrings) {\n\t\tconst existing = byText.get(str.text);\n\t\tif (!existing) {\n\t\t\tbyText.set(str.text, {\n\t\t\t\tkey: str.key,\n\t\t\t\ttext: str.text,\n\t\t\t\t...(str.context ? { context: str.context } : {}),\n\t\t\t\t...(str.formality ? { formality: str.formality } : {}),\n\t\t\t\t...(str.uiRole ? { uiRole: str.uiRole } : {}),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\texisting.context = mergeContext(existing.context, str.context);\n\n\t\tif (!existing.formality && str.formality) {\n\t\t\texisting.formality = str.formality;\n\t\t} else if (\n\t\t\texisting.formality &&\n\t\t\tstr.formality &&\n\t\t\texisting.formality !== str.formality\n\t\t) {\n\t\t\texisting.formality = \"auto\";\n\t\t}\n\n\t\tif (str.key < existing.key) {\n\t\t\texisting.key = str.key;\n\t\t}\n\t}\n\n\treturn Array.from(byText.values());\n}\n\nasync function fetchApiSnapshot(\n\tapi: VocoderAPI,\n\tparams: {\n\t\tbranch: string;\n\t\ttargetLocales: string[];\n\t},\n): Promise<TranslationArtifacts | null> {\n\tconst snapshot = await api.getTranslationSnapshot({\n\t\tbranch: params.branch,\n\t\ttargetLocales: params.targetLocales,\n\t});\n\n\tif (snapshot.status !== \"FOUND\" || !snapshot.translations) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tsource: \"api-snapshot\",\n\t\ttranslations: snapshot.translations,\n\t\tlocaleMetadata: snapshot.localeMetadata,\n\t\tsnapshotBatchId: snapshot.snapshotBatchId,\n\t\tcompletedAt: snapshot.completedAt,\n\t};\n}\n\n/**\n * Main sync command\n */\nexport async function sync(options: TranslateOptions = {}): Promise<number> {\n\tconst startTime = Date.now();\n\tconst projectRoot = process.cwd();\n\n\tp.intro(\"Vocoder Sync\");\n\n\t// Check for API key before doing any work — missing key is an onboarding\n\t// issue, not an error. Show friendly guidance and exit cleanly.\n\tconst mergedConfig = await getMergedConfig(options, options.verbose);\n\tif (!mergedConfig.apiKey) {\n\t\tp.log.warn(\"No API key found. Run init to get started:\");\n\t\tp.log.info(\" npx @vocoder/cli init\");\n\t\tp.log.info(\"\");\n\t\tp.log.info(\n\t\t\t\" Or add your key to .env: VOCODER_API_KEY=vcp_...\",\n\t\t);\n\t\tp.outro(\"Run `npx @vocoder/cli init` to set up your project.\");\n\t\treturn 1;\n\t}\n\n\tconst spinner = p.spinner();\n\n\ttry {\n\t\tconst branch = detectBranch(options.branch);\n\n\t\tspinner.start(\"Loading project configuration\");\n\n\t\tconst localConfig = {\n\t\t\tapiKey: mergedConfig.apiKey,\n\t\t\tapiUrl: mergedConfig.apiUrl || \"https://vocoder.app\",\n\t\t};\n\t\tvalidateLocalConfig(localConfig);\n\n\t\tconst api = new VocoderAPI(localConfig);\n\t\tconst apiConfig = await api.getAppConfig();\n\n\t\tconst requestedMode = mergedConfig.mode;\n\t\tconst waitTimeoutMs = resolveWaitTimeoutMs({\n\t\t\trequestedMaxWaitMs: mergedConfig.maxWaitMs,\n\t\t\tpolicyDefaultMaxWaitMs: apiConfig.syncPolicy.defaultMaxWaitMs,\n\t\t\tfallbackTimeoutMs: 60_000,\n\t\t});\n\n\t\tconst fileConfig = loadVocoderConfig(process.cwd());\n\t\tconst config: ProjectConfig = {\n\t\t\t...localConfig,\n\t\t\t...apiConfig,\n\t\t\tincludePattern: mergedConfig.includePattern,\n\t\t\texcludePattern: mergedConfig.excludePattern,\n\t\t\ttimeout: waitTimeoutMs,\n\t\t\t...(fileConfig?.appIndustry ? { appIndustry: fileConfig.appIndustry } : {}),\n\t\t\t...(fileConfig?.formality ? { formality: fileConfig.formality } : {}),\n\t\t};\n\n\t\tspinner.stop(`Branch: ${highlight(branch)}`);\n\n\t\tif (!options.force && !isTargetBranch(branch, config.targetBranches)) {\n\t\t\tp.log.warn(\n\t\t\t\t`Skipping translations (${highlight(branch)} is not a target branch)`,\n\t\t\t);\n\t\t\tp.log.info(`Target branches: ${config.targetBranches.join(\", \")}`);\n\t\t\tp.log.info(\"Use --force to translate anyway\");\n\t\t\tp.outro(\"\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst patternsDisplay = Array.isArray(config.includePattern)\n\t\t\t? config.includePattern.join(\", \")\n\t\t\t: config.includePattern;\n\n\t\tspinner.start(`Extracting strings from ${patternsDisplay}`);\n\t\tconst extractor = new StringExtractor();\n\t\tconst extractedStrings = await extractor.extractFromProject(\n\t\t\tconfig.includePattern,\n\t\t\tprojectRoot,\n\t\t\tconfig.excludePattern,\n\t\t);\n\n\t\tif (extractedStrings.length === 0) {\n\t\t\tspinner.stop(\"No translatable strings found\");\n\t\t\tp.log.warn(\n\t\t\t\t\"Make sure you are wrapping translatable strings with Vocoder\",\n\t\t\t);\n\t\t\tp.outro(\"\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tspinner.stop(\n\t\t\t`Extracted ${highlight(extractedStrings.length)} strings from ${highlight(patternsDisplay)}`,\n\t\t);\n\n\t\tif (options.verbose) {\n\t\t\tconst sampleLines = extractedStrings\n\t\t\t\t.slice(0, 5)\n\t\t\t\t.map((s: ExtractedString) => ` \"${s.text}\" (${s.file}:${s.line})`);\n\t\t\tif (extractedStrings.length > 5) {\n\t\t\t\tsampleLines.push(` ... and ${extractedStrings.length - 5} more`);\n\t\t\t}\n\t\t\tp.note(sampleLines.join(\"\\n\"), \"Sample strings\");\n\t\t}\n\n\t\tif (options.dryRun) {\n\t\t\tp.note(\n\t\t\t\t[\n\t\t\t\t\t`Strings: ${extractedStrings.length}`,\n\t\t\t\t\t`Branch: ${branch}`,\n\t\t\t\t\t`Target locales: ${config.targetLocales.join(\", \")}`,\n\t\t\t\t\t`Requested mode: ${requestedMode}`,\n\t\t\t\t\t`Max wait: ${waitTimeoutMs}ms`,\n\t\t\t\t\t`No fallback: ${mergedConfig.noFallback ? \"yes\" : \"no\"}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"Dry run - would translate\",\n\t\t\t);\n\t\t\tp.outro(\"No API calls made.\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst repoIdentity = resolveGitRepositoryIdentity();\n\t\tif (!repoIdentity && options.verbose) {\n\t\t\tp.log.warn(\n\t\t\t\t\"Could not detect git remote origin. Sync will continue without repo metadata.\",\n\t\t\t);\n\t\t}\n\t\tconst commitSha = detectCommitSha() ?? undefined;\n\n\t\tconst stringEntries = buildStringEntries(extractedStrings);\n\t\tconst sourceStrings = stringEntries.map((entry) => entry.text);\n\n\t\tif (options.verbose && stringEntries.length !== extractedStrings.length) {\n\t\t\tp.log.info(\n\t\t\t\t`Deduped ${extractedStrings.length} extracted entries into ${stringEntries.length} unique source strings`,\n\t\t\t);\n\t\t}\n\n\t\tconst fingerprint = computeFingerprint(config.shortCode, sourceStrings);\n\n\t\t// Local cache check — skip API submission if translations already exist for this fingerprint.\n\t\tif (!options.force) {\n\t\t\tconst cacheFile = getCacheFilePath(projectRoot, fingerprint);\n\t\t\tif (existsSync(cacheFile)) {\n\t\t\t\tif (options.verbose) {\n\t\t\t\t\tp.log.info(`Cache hit: ${chalk.dim(cacheFile)} (fingerprint ${highlight(fingerprint)})`);\n\t\t\t\t}\n\t\t\t\tconst duration = ((Date.now() - startTime) / 1000).toFixed(1);\n\t\t\t\tp.outro(`Up to date (${duration}s)`);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (options.verbose) {\n\t\t\t\tp.log.info(`No cache for fingerprint ${highlight(fingerprint)} — will submit to API`);\n\t\t\t}\n\t\t}\n\n\t\tspinner.start(\"Submitting strings to Vocoder API\");\n\n\t\tconst batchResponse = await api.submitTranslation(\n\t\t\tbranch,\n\t\t\tstringEntries,\n\t\t\tconfig.targetLocales,\n\t\t\t{\n\t\t\t\trequestedMode,\n\t\t\t\trequestedMaxWaitMs: waitTimeoutMs,\n\t\t\t\tclientRunId: randomUUID(),\n\t\t\t\tforce: options.force,\n\t\t\t\t// Sync appIndustry from vocoder.config.ts to App on every push\n\t\t\t\t...(config.appIndustry ? { appIndustry: config.appIndustry } : {}),\n\t\t\t},\n\t\t\trepoIdentity ? { ...repoIdentity, commitSha } : { commitSha },\n\t\t);\n\n\t\tspinner.stop(\"Strings submitted\");\n\n\t\tconst effectiveMode =\n\t\t\tbatchResponse.effectiveMode ??\n\t\t\tresolveEffectiveModeFromPolicy({\n\t\t\t\tbranch,\n\t\t\t\trequestedMode,\n\t\t\t\tpolicy: config.syncPolicy,\n\t\t\t});\n\n\t\tif (options.verbose) {\n\t\t\tp.log.info(`Batch: ${chalk.dim(batchResponse.batchId)}`);\n\t\t\tp.log.info(`Requested mode: ${requestedMode}`);\n\t\t\tp.log.info(`Effective mode: ${effectiveMode}`);\n\t\t\tp.log.info(`Wait timeout: ${waitTimeoutMs}ms`);\n\t\t\tif (batchResponse.queueStatus) {\n\t\t\t\tp.log.info(`Queue status: ${batchResponse.queueStatus}`);\n\t\t\t}\n\t\t}\n\n\t\tif (batchResponse.status === \"UP_TO_DATE\" && batchResponse.noChanges) {\n\t\t\tp.log.success(`Up to date — ${highlight(batchResponse.totalStrings)} strings, no changes`);\n\t\t} else if (batchResponse.newStrings === 0) {\n\t\t\tconst archivedNote =\n\t\t\t\tbatchResponse.deletedStrings && batchResponse.deletedStrings > 0\n\t\t\t\t\t? `, ${chalk.yellow(batchResponse.deletedStrings)} archived`\n\t\t\t\t\t: \"\";\n\t\t\tp.log.success(`No new strings — ${highlight(batchResponse.totalStrings)} total${archivedNote}, using existing translations`);\n\t\t} else {\n\t\t\tconst statParts = [`${highlight(batchResponse.newStrings)} new, ${highlight(batchResponse.totalStrings)} total`];\n\t\t\tif (batchResponse.deletedStrings && batchResponse.deletedStrings > 0) {\n\t\t\t\tstatParts.push(`${chalk.yellow(batchResponse.deletedStrings)} archived`);\n\t\t\t}\n\t\t\tconst estTime = batchResponse.estimatedTime ? ` (~${batchResponse.estimatedTime}s)` : \"\";\n\t\t\tp.log.info(`${statParts.join(\", \")} → syncing to ${config.targetLocales.join(\", \")}${estTime}`);\n\t\t}\n\n\t\tlet artifacts: TranslationArtifacts | null = null;\n\t\tif (batchResponse.translations) {\n\t\t\tartifacts = {\n\t\t\t\tsource: \"fresh\",\n\t\t\t\ttranslations: batchResponse.translations,\n\t\t\t};\n\t\t}\n\n\t\tlet waitError: Error | null = null;\n\t\tif (\n\t\t\t!artifacts &&\n\t\t\t(effectiveMode === \"required\" || effectiveMode === \"best-effort\")\n\t\t) {\n\t\t\tconst waitTimeoutSecs = Math.round(waitTimeoutMs / 1000);\n\t\t\tspinner.start(`Waiting for translations (max ${waitTimeoutSecs}s)`);\n\n\t\t\tlet lastProgress = 0;\n\t\t\ttry {\n\t\t\t\tconst completion = await api.waitForCompletion(\n\t\t\t\t\tbatchResponse.batchId,\n\t\t\t\t\twaitTimeoutMs,\n\t\t\t\t\t(progress) => {\n\t\t\t\t\t\tconst percent = Math.round(progress * 100);\n\t\t\t\t\t\tif (percent > lastProgress) {\n\t\t\t\t\t\t\tspinner.message(`Translating... ${percent}%`);\n\t\t\t\t\t\t\tlastProgress = percent;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tartifacts = {\n\t\t\t\t\tsource: \"fresh\",\n\t\t\t\t\ttranslations: completion.translations,\n\t\t\t\t\tlocaleMetadata: completion.localeMetadata,\n\t\t\t\t};\n\t\t\t\tspinner.stop(\"Translations complete\");\n\t\t\t} catch (error) {\n\t\t\t\tspinner.stop(\"Translation wait incomplete\");\n\t\t\t\twaitError = error instanceof Error ? error : new Error(String(error));\n\n\t\t\t\tif (effectiveMode === \"required\") {\n\t\t\t\t\tthrow waitError;\n\t\t\t\t}\n\n\t\t\t\tp.log.warn(`Best-effort wait ended early: ${waitError.message}`);\n\t\t\t}\n\t\t}\n\n\t\tif (!artifacts) {\n\t\t\tif (mergedConfig.noFallback) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Fresh translations are not available and fallback is disabled (--no-fallback).\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tspinner.start(\"Loading fallback translations\");\n\n\t\t\tconst localFallback = readLocalCache({\n\t\t\t\tprojectRoot,\n\t\t\t\tfingerprint,\n\t\t\t});\n\n\t\t\tif (localFallback) {\n\t\t\t\tartifacts = localFallback;\n\t\t\t\tspinner.stop(`Using local cached snapshot (${fingerprint})`);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst apiSnapshot = await fetchApiSnapshot(api, {\n\t\t\t\t\t\tbranch,\n\t\t\t\t\t\ttargetLocales: config.targetLocales,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (apiSnapshot) {\n\t\t\t\t\t\tartifacts = apiSnapshot;\n\t\t\t\t\t\tspinner.stop(\"Using latest completed API snapshot\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tspinner.stop(\"No completed API snapshot available\");\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tspinner.stop(\"Failed to fetch API snapshot\");\n\t\t\t\t\tif (options.verbose) {\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t\t: \"Unknown snapshot fetch error\";\n\t\t\t\t\t\tp.log.warn(`Snapshot fetch error: ${message}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!artifacts) {\n\t\t\t\tif (waitError) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`No fallback snapshot available after wait failure: ${waitError.message}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"No fallback snapshot available. Try again shortly or run with --mode required.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst finalTranslations = normalizeTranslations({\n\t\t\tsourceLocale: config.sourceLocale,\n\t\t\ttargetLocales: config.targetLocales,\n\t\t\tsourceStrings,\n\t\t\ttranslations: artifacts.translations,\n\t\t});\n\n\t\ttry {\n\t\t\tconst data = buildTranslationData({\n\t\t\t\tsourceLocale: config.sourceLocale,\n\t\t\t\ttargetLocales: config.targetLocales,\n\t\t\t\tstringEntries,\n\t\t\t\ttranslations: finalTranslations,\n\t\t\t\tlocaleMetadata: artifacts.localeMetadata,\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t});\n\t\t\tconst cachePath = writeCache({ projectRoot, fingerprint, data });\n\t\t\tif (options.verbose) {\n\t\t\t\tp.log.info(`Cache written: ${cachePath}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (options.verbose) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : \"Unknown cache write error\";\n\t\t\t\tp.log.warn(`Failed to write cache: ${message}`);\n\t\t\t}\n\t\t}\n\n\t\tif (artifacts.source !== \"fresh\") {\n\t\t\tconst sourceLabel =\n\t\t\t\tartifacts.source === \"local-cache\"\n\t\t\t\t\t? \"local cached snapshot\"\n\t\t\t\t\t: \"completed API snapshot\";\n\t\t\tp.log.warn(\n\t\t\t\t`Using ${sourceLabel}. New strings may appear after the background sync completes.`,\n\t\t\t);\n\t\t}\n\n\t\tconst duration = ((Date.now() - startTime) / 1000).toFixed(1);\n\t\tp.outro(`Sync complete! (${duration}s)`);\n\t\treturn 0;\n\t} catch (error) {\n\t\tspinner.stop();\n\n\t\tif (error instanceof VocoderAPIError && error.syncPolicyError) {\n\t\t\tp.log.error(error.syncPolicyError.message);\n\t\t\tconst guidance = getSyncPolicyErrorGuidance(error.syncPolicyError);\n\t\t\tfor (const line of guidance) {\n\t\t\t\tp.log.info(line);\n\t\t\t}\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (error instanceof VocoderAPIError && error.limitError) {\n\t\t\tconst { limitError } = error;\n\t\t\tp.log.error(limitError.message);\n\t\t\tconst guidance = getLimitErrorGuidance(limitError);\n\t\t\tfor (const line of guidance) {\n\t\t\t\tp.log.info(line);\n\t\t\t}\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (error instanceof Error) {\n\t\t\tp.log.error(error.message);\n\n\t\t\tconst isInvalidKey =\n\t\t\t\terror.message.toLowerCase().includes(\"invalid api key\") ||\n\t\t\t\t(error instanceof VocoderAPIError && error.status === 401);\n\n\t\t\tif (isInvalidKey) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t\"API key rejected — the project may have been deleted or the key revoked.\",\n\t\t\t\t);\n\t\t\t\tp.log.info(\n\t\t\t\t\t\" Run `npx @vocoder/cli init` to create a new project and key.\",\n\t\t\t\t);\n\t\t\t} else if (error.message.includes(\"git branch\")) {\n\t\t\t\tp.log.warn(\"Run from a git repository, or use:\");\n\t\t\t\tp.log.info(\" vocoder sync --branch main\");\n\t\t\t}\n\n\t\t\tif (options.verbose) {\n\t\t\t\tp.log.info(`Full error: ${error.stack ?? error}`);\n\t\t\t}\n\t\t}\n\n\t\treturn 1;\n\t}\n}\n","import { execSync } from \"node:child_process\";\n\nconst REGEX_SPECIAL_CHARS = /[.+?^${}()|[\\]\\\\]/g;\n\nfunction escapeRegexChar(value: string): string {\n\treturn value.replace(REGEX_SPECIAL_CHARS, \"\\\\$&\");\n}\n\n/**\n * Detects the current git branch from multiple sources in priority order:\n * 1. Explicit --branch flag (passed as parameter)\n * 2. CI environment variables (GitHub Actions, Vercel, Netlify, etc.)\n * 3. Git command (local development)\n *\n * @param override - Optional branch name to override detection\n * @returns The current branch name\n */\nexport function detectBranch(override?: string): string {\n\t// 1. Explicit override (from --branch flag)\n\tif (override) {\n\t\treturn override;\n\t}\n\n\t// 2. CI environment variables\n\tconst envBranch =\n\t\tprocess.env.GITHUB_HEAD_REF || // GitHub Actions (PR source branch)\n\t\tprocess.env.GITHUB_REF_NAME || // GitHub Actions (push)\n\t\tprocess.env.VERCEL_GIT_COMMIT_REF || // Vercel\n\t\tprocess.env.BRANCH || // Netlify\n\t\tprocess.env.CF_PAGES_BRANCH || // Cloudflare Pages\n\t\tprocess.env.CI_COMMIT_REF_NAME || // GitLab CI\n\t\tprocess.env.BITBUCKET_BRANCH || // Bitbucket Pipelines\n\t\tprocess.env.CIRCLE_BRANCH || // CircleCI\n\t\tprocess.env.RENDER_GIT_BRANCH; // Render\n\n\tif (envBranch) {\n\t\treturn envBranch;\n\t}\n\n\t// 3. Git command (local development)\n\ttry {\n\t\tconst branch = execSync(\"git rev-parse --abbrev-ref HEAD\", {\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t}).trim();\n\n\t\treturn branch;\n\t} catch (_error) {\n\t\tthrow new Error(\n\t\t\t\"Failed to detect git branch. Make sure you are in a git repository or set the --branch flag.\",\n\t\t);\n\t}\n}\n\n/**\n * Checks if the current branch is a target branch that should trigger translations\n *\n * @param currentBranch - The current branch name\n * @param targetBranches - List of branches that should trigger translations\n * @returns True if the branch should trigger translations\n */\nexport function isTargetBranch(\n\tcurrentBranch: string,\n\ttargetBranches: string[],\n): boolean {\n\treturn targetBranches.some((pattern) =>\n\t\tmatchBranchPattern(currentBranch, pattern),\n\t);\n}\n\nexport function matchBranchPattern(branch: string, pattern: string): boolean {\n\tconst trimmedPattern = pattern.trim();\n\tif (!trimmedPattern) {\n\t\treturn false;\n\t}\n\n\tlet regexSource = \"^\";\n\tfor (let i = 0; i < trimmedPattern.length; i += 1) {\n\t\tconst char = trimmedPattern[i];\n\t\tif (!char) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"*\") {\n\t\t\tconst next = trimmedPattern[i + 1];\n\t\t\tif (next === \"*\") {\n\t\t\t\tregexSource += \".*\";\n\t\t\t\ti += 1;\n\t\t\t} else {\n\t\t\t\tregexSource += \"[^/]*\";\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tregexSource += escapeRegexChar(char);\n\t}\n\tregexSource += \"$\";\n\n\treturn new RegExp(regexSource).test(branch);\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"./theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { loadVocoderConfig } from \"@vocoder/extractor\";\nimport type {\n\tLocalConfig,\n\tRequestedSyncMode,\n\tTranslateOptions,\n} from \"../types.js\";\n\n// Load .env file if present\nloadEnv();\n\n/**\n * Validates the local configuration\n */\nexport function validateLocalConfig(config: LocalConfig): void {\n\tif (!config.apiKey || config.apiKey.length === 0) {\n\t\tthrow new Error(\"VOCODER_API_KEY is required. Set it in your .env file.\");\n\t}\n\n\tif (!config.apiKey.startsWith(\"vcp_\")) {\n\t\tif (config.apiKey.startsWith(\"vco_\") || config.apiKey.startsWith(\"vcu_\")) {\n\t\t\tthrow new Error(\n\t\t\t\t\"VOCODER_API_KEY must be a project-scoped key (starts with vcp_). Got an org or user key.\",\n\t\t\t);\n\t\t}\n\t\tthrow new Error(\n\t\t\t\"Invalid API key format. Expected a project API key starting with vcp_.\",\n\t\t);\n\t}\n\n\tif (!config.apiUrl || !config.apiUrl.startsWith(\"http\")) {\n\t\tthrow new Error(\"Invalid API URL\");\n\t}\n}\n\n/**\n * Merge configuration from all sources with priority:\n * 1. CLI flags (highest priority)\n * 2. Environment variables\n * 3. Defaults (lowest priority)\n *\n * @param cliOptions - Options from CLI flags\n * @param verbose - Whether to log config sources\n * @returns Merged configuration with source information\n */\nexport async function getMergedConfig(\n\tcliOptions: TranslateOptions,\n\tverbose: boolean = false,\n\t_startDir?: string,\n): Promise<{\n\tincludePattern: string[];\n\texcludePattern: string[];\n\tapiKey?: string;\n\tapiUrl?: string;\n\tmode: RequestedSyncMode;\n\tmaxWaitMs?: number;\n\tnoFallback: boolean;\n\tconfigSources: {\n\t\tincludePattern: string;\n\t\texcludePattern: string;\n\t\tapiKey: string;\n\t\tapiUrl: string;\n\t\tmode: string;\n\t\tmaxWaitMs: string;\n\t\tnoFallback: string;\n\t};\n}> {\n\tconst configSources = {\n\t\tincludePattern: \"default\",\n\t\texcludePattern: \"default\",\n\t\tapiKey: \"environment\",\n\t\tapiUrl: \"default\",\n\t\tmode: \"default\",\n\t\tmaxWaitMs: \"default\",\n\t\tnoFallback: \"default\",\n\t};\n\n\t// 1. Defaults\n\tconst defaults = {\n\t\tincludePattern: [\"**/*.{tsx,jsx,ts,js}\"],\n\t\texcludePattern: [\n\t\t\t\"**/node_modules/**\",\n\t\t\t\"**/.next/**\",\n\t\t\t\"**/.nuxt/**\",\n\t\t\t\"**/.svelte-kit/**\",\n\t\t\t\"**/.output/**\",\n\t\t\t\"**/dist/**\",\n\t\t\t\"**/build/**\",\n\t\t\t\"**/out/**\",\n\t\t\t\"**/.vite/**\",\n\t\t\t\"**/.turbo/**\",\n\t\t\t\"**/coverage/**\",\n\t\t\t\"**/.cache/**\",\n\t\t\t\"**/*.min.js\",\n\t\t\t\"**/*.min.ts\",\n\t\t\t\"**/__generated__/**\",\n\t\t\t\"**/*.test.*\",\n\t\t\t\"**/*.spec.*\",\n\t\t\t\"**/*.stories.*\",\n\t\t\t\"**/__tests__/**\",\n\t\t],\n\t\tapiUrl: \"https://vocoder.app\",\n\t};\n\n\t// 2. vocoder.config.ts — the canonical source for extraction patterns.\n\t// CLI flags still override it for one-off runs.\n\tconst fileConfig = loadVocoderConfig(process.cwd());\n\n\tif (!fileConfig) {\n\t\tp.log.warn(\n\t\t\t`No ${highlight(\"vocoder.config.ts\")} found — run ${highlight(\"npx @vocoder/cli init\")} to generate one.`,\n\t\t);\n\t}\n\n\t// 3. Environment variables (legacy, lower priority than config file)\n\tconst envExtractionPattern = process.env.VOCODER_INCLUDE_PATTERN;\n\tconst envExcludePattern = process.env.VOCODER_EXCLUDE_PATTERN;\n\tconst envApiUrl = process.env.VOCODER_API_URL;\n\tconst envSyncMode = process.env.VOCODER_SYNC_MODE;\n\tconst envSyncMaxWaitMs = process.env.VOCODER_SYNC_MAX_WAIT_MS;\n\tconst envSyncNoFallback = process.env.VOCODER_SYNC_NO_FALLBACK;\n\n\t// 4. Merge with priority: CLI flag > vocoder.config.ts > env > defaults\n\n\t// Extract patterns (include)\n\tlet includePattern: string[];\n\tif (cliOptions.include && cliOptions.include.length > 0) {\n\t\tincludePattern = cliOptions.include;\n\t\tconfigSources.includePattern = \"CLI flag\";\n\t} else if (fileConfig?.include && fileConfig.include.length > 0) {\n\t\tincludePattern = fileConfig.include;\n\t\tconfigSources.includePattern = \"vocoder.config\";\n\t} else if (envExtractionPattern) {\n\t\tincludePattern = [envExtractionPattern];\n\t\tconfigSources.includePattern = \"environment\";\n\t} else {\n\t\tincludePattern = defaults.includePattern;\n\t}\n\n\t// Exclude patterns\n\tlet excludePattern: string[];\n\tif (cliOptions.exclude && cliOptions.exclude.length > 0) {\n\t\texcludePattern = cliOptions.exclude;\n\t\tconfigSources.excludePattern = \"CLI flag\";\n\t} else if (fileConfig?.exclude && fileConfig.exclude.length > 0) {\n\t\texcludePattern = fileConfig.exclude;\n\t\tconfigSources.excludePattern = \"vocoder.config\";\n\t} else if (envExcludePattern) {\n\t\texcludePattern = envExcludePattern\n\t\t\t.split(\",\")\n\t\t\t.map((p: string) => p.trim())\n\t\t\t.filter(Boolean);\n\t\tconfigSources.excludePattern = \"environment\";\n\t} else {\n\t\texcludePattern = defaults.excludePattern;\n\t}\n\n\t// API key (from env)\n\tlet apiKey: string | undefined;\n\tif (process.env.VOCODER_API_KEY) {\n\t\tapiKey = process.env.VOCODER_API_KEY;\n\t\tconfigSources.apiKey = \"environment\";\n\t}\n\n\t// API URL\n\tlet apiUrl: string;\n\tif (envApiUrl) {\n\t\tapiUrl = envApiUrl;\n\t\tconfigSources.apiUrl = \"environment\";\n\t} else {\n\t\tapiUrl = defaults.apiUrl;\n\t}\n\n\tconst modeCandidates = [\"auto\", \"required\", \"best-effort\"] as const;\n\tlet mode: RequestedSyncMode = \"auto\";\n\tif (cliOptions.mode && modeCandidates.includes(cliOptions.mode)) {\n\t\tmode = cliOptions.mode;\n\t\tconfigSources.mode = \"CLI flag\";\n\t} else if (\n\t\tenvSyncMode &&\n\t\tmodeCandidates.includes(envSyncMode as RequestedSyncMode)\n\t) {\n\t\tmode = envSyncMode as RequestedSyncMode;\n\t\tconfigSources.mode = \"environment\";\n\t}\n\n\tlet maxWaitMs: number | undefined;\n\tif (\n\t\ttypeof cliOptions.maxWaitMs === \"number\" &&\n\t\tNumber.isFinite(cliOptions.maxWaitMs) &&\n\t\tcliOptions.maxWaitMs > 0\n\t) {\n\t\tmaxWaitMs = Math.floor(cliOptions.maxWaitMs);\n\t\tconfigSources.maxWaitMs = \"CLI flag\";\n\t} else if (envSyncMaxWaitMs) {\n\t\tconst parsed = Number.parseInt(envSyncMaxWaitMs, 10);\n\t\tif (Number.isFinite(parsed) && parsed > 0) {\n\t\t\tmaxWaitMs = parsed;\n\t\t\tconfigSources.maxWaitMs = \"environment\";\n\t\t}\n\t}\n\n\tlet noFallback = false;\n\tif (typeof cliOptions.noFallback === \"boolean\") {\n\t\tnoFallback = cliOptions.noFallback;\n\t\tconfigSources.noFallback = \"CLI flag\";\n\t} else if (envSyncNoFallback) {\n\t\tnoFallback = [\"1\", \"true\", \"yes\", \"on\"].includes(\n\t\t\tenvSyncNoFallback.toLowerCase(),\n\t\t);\n\t\tconfigSources.noFallback = \"environment\";\n\t}\n\n\t// Log config sources in verbose mode\n\tif (verbose) {\n\t\tconst lines = [\n\t\t\t`Include patterns: ${highlight(configSources.includePattern)}`,\n\t\t\t...(excludePattern.length > 0\n\t\t\t\t? [`Exclude patterns: ${highlight(configSources.excludePattern)}`]\n\t\t\t\t: []),\n\t\t\t`API key: ${highlight(configSources.apiKey)}`,\n\t\t\t`API URL: ${highlight(configSources.apiUrl)}`,\n\t\t\t`Sync mode: ${highlight(configSources.mode)}`,\n\t\t\t...(maxWaitMs\n\t\t\t\t? [`Max wait: ${highlight(String(configSources.maxWaitMs))}`]\n\t\t\t\t: []),\n\t\t\t`No fallback: ${highlight(String(configSources.noFallback))}`,\n\t\t];\n\t\tp.note(lines.join(\"\\n\"), \"Configuration sources\");\n\t}\n\n\treturn {\n\t\tincludePattern,\n\t\texcludePattern,\n\t\tapiKey,\n\t\tapiUrl,\n\t\tmode,\n\t\tmaxWaitMs,\n\t\tnoFallback,\n\t\tconfigSources,\n\t};\n}\n","import * as p from \"@clack/prompts\";\nimport { VocoderAPI } from \"../utils/api.js\";\nimport { clearAuthData, readAuthData } from \"../utils/auth-store.js\";\n\nexport interface LogoutOptions {\n\tapiUrl?: string;\n}\n\nexport async function logout(options: LogoutOptions = {}): Promise<number> {\n\tconst stored = readAuthData();\n\n\tif (!stored) {\n\t\tp.log.info(\"Not currently authenticated.\");\n\t\treturn 0;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? stored.apiUrl ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\n\ttry {\n\t\tawait api.revokeCliToken(stored.token);\n\t} catch {\n\t\t// Ignore errors — we still clear local data even if the server call fails\n\t}\n\n\tclearAuthData();\n\tp.log.success(`Logged out (was ${stored.email})`);\n\treturn 0;\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI } from \"../utils/api.js\";\n\nloadEnv();\n\nexport interface AppConfigOptions {\n\tapiUrl?: string;\n}\n\n/**\n * Displays the current Vocoder app configuration.\n *\n * Shows: project name, organization, source locale, target locales,\n * target branches, primary branch, and sync policy settings.\n *\n * Reads the app API key from VOCODER_API_KEY.\n * Endpoint: GET /api/cli/config\n *\n * @throws If VOCODER_API_KEY is missing or invalid.\n */\nexport async function appConfig(options: AppConfigOptions = {}): Promise<number> {\n\tconst apiKey = process.env.VOCODER_API_KEY;\n\tif (!apiKey) {\n\t\tp.log.error(\n\t\t\t\"VOCODER_API_KEY is not set. Run `npx @vocoder/cli init` to set up your project.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiKey, apiUrl });\n\n\ttry {\n\t\tconst config = await api.getAppConfig();\n\n\t\tconst lines = [\n\t\t\t`App: ${chalk.bold(config.projectName)}`,\n\t\t\t`Organization: ${config.organizationName}`,\n\t\t\t`Source locale: ${highlight(config.sourceLocale)}`,\n\t\t\t`Target locales: ${\n\t\t\t\tconfig.targetLocales.length > 0\n\t\t\t\t\t? config.targetLocales.map((l) => highlight(l)).join(\", \")\n\t\t\t\t\t: chalk.dim(\"(none)\")\n\t\t\t}`,\n\t\t\t`Target branches: ${config.targetBranches.map((b) => highlight(b)).join(\", \")}`,\n\t\t\t...(config.primaryBranch\n\t\t\t\t? [`Primary branch: ${highlight(config.primaryBranch)}`]\n\t\t\t\t: []),\n\t\t\t`Sync policy:`,\n\t\t\t` Blocking branches: ${config.syncPolicy.blockingBranches.map((b) => highlight(b)).join(\", \")}`,\n\t\t\t` Blocking mode: ${highlight(config.syncPolicy.blockingMode)}`,\n\t\t\t` Non-blocking mode: ${highlight(config.syncPolicy.nonBlockingMode)}`,\n\t\t\t` Max wait: ${highlight(String(config.syncPolicy.defaultMaxWaitMs))} ms`,\n\t\t];\n\n\t\tp.note(lines.join(\"\\n\"), `${config.projectName} — app config`);\n\t\treturn 0;\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to fetch project config.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI } from \"../utils/api.js\";\nimport { detectBranch } from \"../utils/branch.js\";\n\nloadEnv();\n\nexport interface TranslationsOptions {\n\t/** Git branch. Auto-detected from git/CI env if omitted. */\n\tbranch?: string;\n\t/** Specific target locale to fetch. All configured locales if omitted. */\n\tlocale?: string;\n\t/**\n\t * Output directory for locale JSON files.\n\t * When set, writes one <locale>.json per locale to this directory.\n\t * When omitted, prints the full snapshot as JSON to stdout.\n\t */\n\toutput?: string;\n\tapiUrl?: string;\n}\n\n/**\n * Downloads the current translation snapshot for the project.\n *\n * With --output <dir>: writes one <locale>.json file per locale to the\n * specified directory. Each file shape: { \"source text\": \"translated text\" }.\n *\n * Without --output: prints the full snapshot JSON to stdout, suitable\n * for piping or programmatic use.\n *\n * Reads the project API key from VOCODER_API_KEY.\n * Endpoint: GET /api/cli/sync/snapshot\n *\n * @param options.branch Git branch (auto-detected from git/CI if omitted).\n * @param options.locale Specific target locale; all configured locales if omitted.\n * @param options.output Output directory. Omit to print to stdout.\n *\n * @throws If VOCODER_API_KEY is missing or invalid.\n */\nexport async function getTranslations(options: TranslationsOptions = {}): Promise<number> {\n\tconst apiKey = process.env.VOCODER_API_KEY;\n\tif (!apiKey) {\n\t\tp.log.error(\n\t\t\t\"VOCODER_API_KEY is not set. Run `npx @vocoder/cli init` to set up your project.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiKey, apiUrl });\n\n\tlet branch: string;\n\ttry {\n\t\tbranch = detectBranch(options.branch);\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to detect branch.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst spinner = p.spinner();\n\tspinner.start(`Fetching translations for ${highlight(branch)}…`);\n\n\ttry {\n\t\t// Fetch the project config to resolve which target locales to request\n\t\tconst projectConfig = await api.getAppConfig();\n\t\tconst targetLocales = options.locale\n\t\t\t? [options.locale]\n\t\t\t: projectConfig.targetLocales;\n\n\t\tif (targetLocales.length === 0) {\n\t\t\tspinner.stop(\"No target locales configured.\");\n\t\t\tp.log.info(\"Add target locales with `vocoder locales add <code>`.\");\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst snapshot = await api.getTranslationSnapshot({ branch, targetLocales });\n\t\tspinner.stop(`Fetched translations for ${highlight(branch)}`);\n\n\t\tif (snapshot.status === \"NOT_FOUND\") {\n\t\t\tp.log.warn(\n\t\t\t\t`No translation snapshot found for branch \"${branch}\". ` +\n\t\t\t\t\t\"Run `vocoder sync` to generate one.\",\n\t\t\t);\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst translations = snapshot.translations ?? {};\n\n\t\tif (options.output) {\n\t\t\twriteLocaleFiles(translations, options.output);\n\t\t} else {\n\t\t\t// stdout — raw JSON for piping/programmatic use\n\t\t\tprocess.stdout.write(JSON.stringify(translations, null, 2));\n\t\t\tprocess.stdout.write(\"\\n\");\n\t\t}\n\n\t\treturn 0;\n\t} catch (error) {\n\t\tspinner.stop(\"Failed to fetch translations.\");\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Unknown error.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n\n/**\n * Writes one <locale>.json file per locale to the output directory.\n * Creates the directory if it does not exist.\n * Each file shape: { \"source text\": \"translated text\" }\n */\nfunction writeLocaleFiles(\n\ttranslations: Record<string, Record<string, string>>,\n\toutputDir: string,\n): void {\n\tmkdirSync(outputDir, { recursive: true });\n\n\tfor (const [locale, strings] of Object.entries(translations)) {\n\t\tconst filePath = join(outputDir, `${locale}.json`);\n\t\twriteFileSync(filePath, JSON.stringify(strings, null, 2) + \"\\n\", \"utf-8\");\n\t\tp.log.success(`Wrote ${highlight(filePath)}`);\n\t}\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport { readAuthData } from \"../utils/auth-store.js\";\nimport { resolveGitRepositoryIdentity } from \"../utils/git-identity.js\";\nimport { getLimitErrorGuidance } from \"./sync.js\";\n\nloadEnv();\n\nexport interface CreateAppOptions {\n\t/** Project display name (required). */\n\tname: string;\n\t/** BCP 47 source locale code, e.g. \"en\" (required). */\n\tsourceLocale: string;\n\t/** Comma-separated target locale codes, e.g. \"fr,de,pt-BR\". */\n\ttargetLocales?: string;\n\t/** Comma-separated branch names to enable sync on. Defaults to \"main\". */\n\ttargetBranches?: string;\n\t/** Organization ID of the workspace to create the project in (required). */\n\tworkspace: string;\n\t/**\n\t * Explicit git repository canonical, e.g. \"github:owner/repo\".\n\t * Auto-detected from git remote if omitted.\n\t */\n\trepo?: string;\n\t/**\n\t * App directory within the repository for monorepos, e.g. \"apps/web\".\n\t * Defaults to \".\" (repo root).\n\t */\n\tappDir?: string;\n\tapiUrl?: string;\n}\n\n/**\n * Creates a new Vocoder project without the interactive init flow.\n *\n * Requires a valid user token in the local auth store (run `vocoder init` first).\n * Prints the generated VOCODER_API_KEY to stdout on success.\n *\n * Git identity is auto-detected from the git remote. The detected repository\n * must be accessible via the workspace's GitHub App installation for\n * push-based sync to function. Use --repo to override auto-detection, or\n * omit repo binding entirely if not in a git repository.\n *\n * Endpoint: POST /api/cli/projects\n *\n * @param options.name Project display name (required).\n * @param options.sourceLocale Source language BCP 47 code (required).\n * @param options.targetLocales Comma-separated target locale codes.\n * @param options.targetBranches Comma-separated branch names (default: \"main\").\n * @param options.workspace Organization ID (required).\n * @param options.repo Git repo canonical override.\n * @param options.appDir App directory for monorepos (default: \".\").\n *\n * @throws If user token is missing, workspace is invalid, or the plan's\n * maxProjects limit is exceeded.\n */\nexport async function createApp(options: CreateAppOptions): Promise<number> {\n\tconst authData = readAuthData();\n\tif (!authData) {\n\t\tp.log.error(\n\t\t\t\"Not logged in. Run `npx @vocoder/cli init` to authenticate first.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiKey: \"\", apiUrl });\n\n\t// Resolve repo identity — auto-detect if not overridden\n\tlet repoCanonical: string | undefined;\n\tlet appDir = options.appDir ?? \".\";\n\n\tif (options.repo) {\n\t\trepoCanonical = options.repo;\n\t} else {\n\t\tconst identity = resolveGitRepositoryIdentity();\n\t\tif (identity) {\n\t\t\trepoCanonical = identity.repoCanonical;\n\t\t\t// Only override appDir from git if the caller didn't specify one\n\t\t\tif (!options.appDir && identity.repoAppDir) {\n\t\t\t\tappDir = identity.repoAppDir;\n\t\t\t}\n\t\t} else {\n\t\t\tp.log.warn(\n\t\t\t\t\"Could not detect a git remote. The project will be created without repo binding — \" +\n\t\t\t\t\t\"sync-on-push will not function until a repository is connected via the Vocoder dashboard.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tconst targetLocales = options.targetLocales\n\t\t? options.targetLocales.split(\",\").map((l) => l.trim()).filter(Boolean)\n\t\t: [];\n\n\tconst targetBranches = options.targetBranches\n\t\t? options.targetBranches.split(\",\").map((b) => b.trim()).filter(Boolean)\n\t\t: [\"main\"];\n\n\tconst spinner = p.spinner();\n\tspinner.start(`Creating app \"${options.name}\"…`);\n\n\ttry {\n\t\tconst result = await api.createProject(authData.token, {\n\t\t\torganizationId: options.workspace,\n\t\t\tname: options.name,\n\t\t\tsourceLocale: options.sourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t\tappDirs: [appDir],\n\t\t\t...(repoCanonical ? { repoCanonical } : {}),\n\t\t});\n\n\t\tspinner.stop(`Created app ${chalk.bold(result.projectName)}`);\n\n\t\tconst lines = [\n\t\t\t`Project ID: ${result.projectId}`,\n\t\t\t`Source locale: ${highlight(result.sourceLocale)}`,\n\t\t\t`Target locales: ${result.targetLocales.length > 0 ? result.targetLocales.map((l) => highlight(l)).join(\", \") : chalk.dim(\"(none)\")}`,\n\t\t\t`Branches: ${result.targetBranches.map((b) => highlight(b)).join(\", \")}`,\n\t\t\t...(repoCanonical\n\t\t\t\t? [`Repository: ${highlight(repoCanonical)}${appDir !== \".\" ? ` (${appDir})` : \"\"}`]\n\t\t\t\t: []),\n\t\t\t\"\",\n\t\t\t`Add this to your .env file:`,\n\t\t\t` ${chalk.bold(\"VOCODER_API_KEY\")}=${highlight(result.apiKey)}`,\n\t\t];\n\n\t\tp.note(lines.join(\"\\n\"), \"Project created\");\n\n\t\tif (!result.repositoryBound && repoCanonical) {\n\t\t\tp.log.warn(\n\t\t\t\t`Repository \"${repoCanonical}\" was not automatically connected. ` +\n\t\t\t\t\t\"Ensure your GitHub App installation covers this repository.\",\n\t\t\t);\n\t\t}\n\n\t\treturn 0;\n\t} catch (error) {\n\t\tspinner.stop(\"Failed to create project.\");\n\n\t\tif (error instanceof VocoderAPIError && error.limitError) {\n\t\t\tconst { limitError } = error;\n\t\t\tp.log.error(limitError.message);\n\t\t\tfor (const line of getLimitErrorGuidance(limitError)) {\n\t\t\t\tp.log.info(line);\n\t\t\t}\n\t\t\treturn 1;\n\t\t}\n\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Unknown error.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { VocoderAPI } from \"../utils/api.js\";\nimport { readAuthData } from \"../utils/auth-store.js\";\n\nexport interface WhoamiOptions {\n\tapiUrl?: string;\n}\n\nexport async function whoami(options: WhoamiOptions = {}): Promise<number> {\n\tconst stored = readAuthData();\n\n\tif (!stored) {\n\t\tp.log.info(\"Not logged in. Run `vocoder init` to authenticate.\");\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? stored.apiUrl ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\n\ttry {\n\t\tconst info = await api.getCliUserInfo(stored.token);\n\t\tp.log.info(`Logged in as ${chalk.bold(info.email)}`);\n\t\tif (info.name) {\n\t\t\tp.log.info(`Name: ${info.name}`);\n\t\t}\n\t\tp.log.info(`API: ${apiUrl}`);\n\t\treturn 0;\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Stored credentials are invalid or expired. Run `vocoder init` to re-authenticate.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n"],"mappings":"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","names":["p","execSync","spawn","existsSync","writeFileSync","p","URL","resolve","resolve","p","chalk","isCancel","chalk","isCancel","isCancel","Prompt","p","S_BAR","S_BAR_END","S_ACTIVE","S_SUBMIT","S_CANCEL","S_ERROR","symbol","MAX_VISIBLE","buildList","Prompt","isCancel","chalk","chalk","join","execSync","p","chalk","resolve","tryOpenBrowser","spawn","chalk","execSync","join","existsSync","writeFileSync","anonApi","spinner","options","p","chalk","loadEnv","existsSync","readFileSync","writeFileSync","join","p","chalk","execSync","p","loadEnv","loadEnv","p","join","existsSync","readFileSync","writeFileSync","lines","spinner","chalk","duration","loadEnv","spinner","chalk","p","p","chalk","loadEnv","loadEnv","chalk","mkdirSync","writeFileSync","join","p","loadEnv","loadEnv","spinner","mkdirSync","join","writeFileSync","p","chalk","loadEnv","loadEnv","spinner","chalk","p","chalk","info","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/bin.ts","../src/commands/init.ts","../src/utils/write-config.ts","../src/utils/github-connect.ts","../src/utils/local-server.ts","../src/utils/project-create.ts","../src/utils/branch-select.ts","../src/utils/theme.ts","../src/utils/locale-search.ts","../src/utils/git-identity.ts","../src/utils/workspace.ts","../src/commands/locales.ts","../src/commands/sync.ts","../src/utils/branch.ts","../src/utils/config.ts","../src/commands/logout.ts","../src/commands/app-config.ts","../src/commands/translations.ts","../src/commands/create-app.ts","../src/commands/whoami.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { init } from \"./commands/init.js\";\nimport {\n\taddLocales,\n\tlistProjectLocales,\n\tlistSupportedLocales,\n\tremoveLocales,\n} from \"./commands/locales.js\";\nimport { logout } from \"./commands/logout.js\";\nimport { appConfig } from \"./commands/app-config.js\";\nimport { sync } from \"./commands/sync.js\";\nimport { getTranslations } from \"./commands/translations.js\";\nimport { createApp } from \"./commands/create-app.js\";\nimport { whoami } from \"./commands/whoami.js\";\n\n/**\n * Collector function for repeated CLI options\n * Allows multiple --include or --exclude flags\n */\nfunction collect(value: string, previous: string[] = []): string[] {\n\treturn previous.concat([value]);\n}\n\nasync function runCommand(\n\tcommand: (options: any) => Promise<number>,\n\toptions: any,\n): Promise<void> {\n\tconst exitCode = await command(options);\n\t// Force exit so open stdin handles from readline/clack don't stall the process.\n\tprocess.exit(exitCode);\n}\n\nconst program = new Command();\n\nprogram\n\t.name(\"vocoder\")\n\t.description(\"Vocoder CLI - Project setup and string extraction\")\n\t.version(\"0.1.5\");\n\nprogram\n\t.command(\"init\")\n\t.description(\"Authenticate and provision Vocoder for this project\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.option(\"--yes\", \"Allow overwriting existing local config values\")\n\t.option(\n\t\t\"--ci\",\n\t\t\"Non-interactive mode: print auth URL to stdout, skip browser open\",\n\t)\n\t.option(\"--app-name <name>\", \"Starter app name to create\")\n\t.option(\"--source-locale <locale>\", \"Source locale for the starter project\")\n\t.option(\n\t\t\"--target-locales <list>\",\n\t\t\"Comma-separated target locales (e.g. es,fr,de)\",\n\t)\n\t.action((options) => runCommand(init, options));\n\nprogram\n\t.command(\"sync\")\n\t.description(\"Extract strings and sync translations\")\n\t.option(\"--branch <branch>\", \"Override detected branch\")\n\t.option(\"--mode <mode>\", \"Sync mode: auto, required, best-effort\", \"auto\")\n\t.option(\"--max-wait <ms>\", \"Max wait for translations (ms)\")\n\t.option(\"--force\", \"Force re-extraction even if no changes\")\n\t.option(\"--dry-run\", \"Preview without syncing\")\n\t.option(\"--no-fallback\", \"Disable fallback to cached translations\")\n\t.option(\"--include <pattern>\", \"Include glob pattern\", collect, [])\n\t.option(\"--exclude <pattern>\", \"Exclude glob pattern\", collect, [])\n\t.option(\"--verbose\", \"Detailed output\")\n\t.action((options) => {\n\t\tconst translated: Record<string, unknown> = { ...options };\n\t\tif (options.maxWait) translated.maxWaitMs = Number(options.maxWait);\n\t\tif (options.fallback === false) translated.noFallback = true;\n\t\treturn runCommand(sync, translated);\n\t});\n\nprogram\n\t.command(\"logout\")\n\t.description(\"Log out and remove stored credentials\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(logout, options));\n\nprogram\n\t.command(\"whoami\")\n\t.description(\"Show the currently authenticated user\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(whoami, options));\n\n// ── Project management ────────────────────────────────────────────────────────\n\nconst localesCmd = program\n\t.command(\"locales\")\n\t.description(\"Manage project target locales\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(listProjectLocales, options));\n\nlocalesCmd\n\t.command(\"add <codes...>\")\n\t.description(\"Add one or more target locales by BCP 47 code (e.g. fr de pt-BR)\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((codes: string[], options) =>\n\t\trunCommand((opts) => addLocales(codes, opts), options),\n\t);\n\nlocalesCmd\n\t.command(\"remove <codes...>\")\n\t.description(\"Remove one or more target locales by BCP 47 code\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((codes: string[], options) =>\n\t\trunCommand((opts) => removeLocales(codes, opts), options),\n\t);\n\nlocalesCmd\n\t.command(\"supported\")\n\t.description(\"List all locales supported by Vocoder\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(listSupportedLocales, options));\n\nprogram\n\t.command(\"project\")\n\t.description(\"Show current app configuration\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(appConfig, options));\n\nprogram\n\t.command(\"translations\")\n\t.description(\"Download the current translation snapshot\")\n\t.option(\"--branch <branch>\", \"Git branch (auto-detected if omitted)\")\n\t.option(\"--locale <locale>\", \"Fetch a specific locale only\")\n\t.option(\"--output <dir>\", \"Write locale JSON files to this directory\")\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => runCommand(getTranslations, options));\n\nprogram\n\t.command(\"create-app\")\n\t.description(\"Create a new Vocoder app (requires prior `vocoder init`)\")\n\t.requiredOption(\"--name <name>\", \"App display name\")\n\t.requiredOption(\"--source-locale <code>\", \"Source language BCP 47 code (e.g. en)\")\n\t.requiredOption(\"--workspace <org-id>\", \"Workspace organization ID\")\n\t.option(\n\t\t\"--target-locales <codes>\",\n\t\t\"Comma-separated target locale codes (e.g. fr,de,pt-BR)\",\n\t)\n\t.option(\n\t\t\"--target-branches <branches>\",\n\t\t\"Comma-separated branch names to sync (default: main)\",\n\t)\n\t.option(\n\t\t\"--repo <canonical>\",\n\t\t\"Git repo canonical (e.g. github:owner/repo). Auto-detected from git remote if omitted.\",\n\t)\n\t.option(\n\t\t\"--app-dir <path>\",\n\t\t\"App directory within the repo for monorepos (default: .)\",\n\t)\n\t.option(\"--api-url <url>\", \"Override Vocoder API URL\")\n\t.action((options) => {\n\t\tconst translated = {\n\t\t\t...options,\n\t\t\t// Commander camelCases dashed options\n\t\t\tsourceLocale: options.sourceLocale,\n\t\t\ttargetLocales: options.targetLocales,\n\t\t\ttargetBranches: options.targetBranches,\n\t\t\tworkspace: options.workspace,\n\t\t};\n\t\treturn runCommand(createApp, translated);\n\t});\n\nprogram.parse(process.argv);\n","import * as p from \"@clack/prompts\";\n\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport {\n\tbuildInstallCommand,\n\tdetectLocalEcosystem,\n\tgetPackagesToInstall,\n} from \"../utils/detect-local.js\";\nimport {\n\tclearAuthData,\n\treadAuthData,\n\twriteAuthData,\n\tverifyStoredAuth,\n} from \"../utils/auth-store.js\";\nimport { execSync, spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { findExistingConfig, writeVocoderConfig } from \"../utils/write-config.js\";\nimport {\n\trunGitHubDiscoveryFlow,\n\trunGitHubInstallFlow,\n\tselectGitHubInstallation,\n} from \"../utils/github-connect.js\";\nimport {\n\trunAppCreate,\n\trunProjectCreate,\n} from \"../utils/project-create.js\";\n\nimport type { InitOptions } from \"../types.js\";\nimport chalk from \"chalk\";\nimport { highlight, info } from \"../utils/theme.js\";\nimport { getSetupSnippets } from \"../utils/setup-snippets.js\";\nimport { join } from \"node:path\";\nimport { config as loadEnv } from \"dotenv\";\nimport { resolveGitContext } from \"../utils/git-identity.js\";\nimport { selectWorkspace } from \"../utils/workspace.js\";\nimport { startCallbackServer } from \"../utils/local-server.js\";\n\nloadEnv();\n\nconst SUBSCRIPTION_SETTINGS_PATH =\n\t\"/dashboard/workspace/settings?tab=subscription\";\n\nasync function sleep(ms: number): Promise<void> {\n\tawait new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n\tif (!process.stdout.isTTY || process.env.CI === \"true\") {\n\t\treturn false;\n\t}\n\n\tlet command: string;\n\tlet args: string[];\n\n\tif (process.platform === \"darwin\") {\n\t\tcommand = \"open\";\n\t\targs = [url];\n\t} else if (process.platform === \"win32\") {\n\t\tcommand = \"rundll32\";\n\t\targs = [\"url.dll,FileProtocolHandler\", url];\n\t} else {\n\t\tcommand = \"xdg-open\";\n\t\targs = [url];\n\t}\n\n\treturn await new Promise<boolean>((resolve) => {\n\t\ttry {\n\t\t\tconst child = spawn(command, args, {\n\t\t\t\tdetached: true,\n\t\t\t\tstdio: \"ignore\",\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\n\t\t\tlet settled = false;\n\t\t\tchild.once(\"spawn\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tchild.unref();\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t\tchild.once(\"error\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t});\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t}, 300);\n\t\t} catch {\n\t\t\tresolve(false);\n\t\t}\n\t});\n}\n\nfunction isPlanLimitFailure(message?: string): boolean {\n\tif (!message) return false;\n\treturn /limit|upgrade/i.test(message);\n}\n\nfunction getSubscriptionSettingsUrl(apiUrl: string): string {\n\treturn new URL(SUBSCRIPTION_SETTINGS_PATH, apiUrl).toString();\n}\n\nfunction printPlanLimitMessage(apiUrl: string, message: string): void {\n\tp.log.error(`You are over your plan limits.\\n ${message}`);\n\tp.log.info(`Manage subscription: ${getSubscriptionSettingsUrl(apiUrl)}`);\n}\n\ninterface ScaffoldParams {\n\tsourceLocale: string;\n\ttargetBranches: string[];\n\tappDir?: string;\n}\n\nfunction runScaffold(params: ScaffoldParams): void {\n\tconst { sourceLocale, targetBranches, appDir } = params;\n\n\tconst detection = detectLocalEcosystem();\n\tconst useTypeScript = detection.isTypeScript;\n\n\tif (detection.ecosystem) {\n\t\tconst frameworkLabel = detection.framework ?? detection.ecosystem;\n\t\tconst pmLabel = detection.packageManager;\n\t\tp.log.info(`Detected: ${chalk.bold(frameworkLabel)} (${pmLabel})`);\n\t}\n\n\tconst { devPackages, runtimePackages } = getPackagesToInstall(detection);\n\tconst allPackages = [...devPackages, ...runtimePackages];\n\tif (allPackages.length > 0) {\n\t\tp.log.info(\"\");\n\t\tconst installSpinner = p.spinner();\n\t\tinstallSpinner.start(`Installing ${allPackages.join(\", \")}...`);\n\n\t\ttry {\n\t\t\tif (devPackages.length > 0) {\n\t\t\t\texecSync(\n\t\t\t\t\tbuildInstallCommand(detection.packageManager, devPackages, true),\n\t\t\t\t\t{ stdio: \"pipe\", cwd: process.cwd() },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (runtimePackages.length > 0) {\n\t\t\t\texecSync(\n\t\t\t\t\tbuildInstallCommand(detection.packageManager, runtimePackages, false),\n\t\t\t\t\t{ stdio: \"pipe\", cwd: process.cwd() },\n\t\t\t\t);\n\t\t\t}\n\t\t\tinstallSpinner.stop(`Installed ${allPackages.join(\", \")}`);\n\t\t} catch {\n\t\t\tinstallSpinner.stop(\"Package installation failed\");\n\t\t\tconst cmds = [\n\t\t\t\tdevPackages.length > 0\n\t\t\t\t\t? buildInstallCommand(detection.packageManager, devPackages, true)\n\t\t\t\t\t: null,\n\t\t\t\truntimePackages.length > 0\n\t\t\t\t\t? buildInstallCommand(detection.packageManager, runtimePackages, false)\n\t\t\t\t\t: null,\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\" && \");\n\t\t\tp.log.warn(`Run manually: ${highlight(cmds)}`);\n\t\t}\n\t} else if (detection.ecosystem) {\n\t\tp.log.info(`Packages: ${chalk.green(\"already installed\")}`);\n\t}\n\n\tconst snippets = getSetupSnippets({\n\t\tframework: detection.framework,\n\t\tecosystem: detection.ecosystem,\n\t\tsourceLocale,\n\t\ttargetBranches,\n\t\tappDir,\n\t});\n\n\tconst steps: Array<{ label: string; hint: string; code: string }> = [];\n\n\tif (snippets.pluginStep) {\n\t\tsteps.push({\n\t\t\tlabel: snippets.pluginStep.file,\n\t\t\thint: \"register the build plugin so Vocoder can extract your strings\",\n\t\t\tcode: snippets.pluginStep.code,\n\t\t});\n\t}\n\n\tif (snippets.providerStep) {\n\t\tsteps.push({\n\t\t\tlabel: snippets.providerStep.file,\n\t\t\thint: \"wrap your app so translations load at runtime\",\n\t\t\tcode: snippets.providerStep.code,\n\t\t});\n\t}\n\n\tsteps.push({\n\t\tlabel: \"wrap translatable text\",\n\t\thint: \"mark strings for extraction — Vocoder picks these up on push\",\n\t\tcode: snippets.wrapStep.code,\n\t});\n\n\tp.log.message(\"\");\n\tp.log.message(chalk.bold(\"Finish setup in your code\"));\n\tp.log.message(\"\");\n\n\tfor (let i = 0; i < steps.length; i++) {\n\t\tconst step = steps[i]!;\n\t\tp.log.step(\n\t\t\t`${chalk.bold(step.label)} ${chalk.dim(`— ${step.hint}`)}`,\n\t\t);\n\t\tprintCodeBlock(step.code);\n\t\tif (i < steps.length - 1) p.log.message(\"\");\n\t}\n\n\t// Write vocoder.config.{ts,js} if not already present\n\tconst written = writeVocoderConfig({ targetBranches, useTypeScript });\n\tif (written) {\n\t\tp.log.success(`Created ${highlight(written)}`);\n\t} else if (!findExistingConfig(process.cwd())) {\n\t\tconst ext = useTypeScript ? \"ts\" : \"js\";\n\t\tp.log.warn(\n\t\t\t`Could not write vocoder.config.${ext} — create it manually with your extraction patterns.`,\n\t\t);\n\t}\n\n\tp.log.message(\"\");\n\tconst branchList =\n\t\ttargetBranches.length > 0\n\t\t\t? targetBranches.map((b) => highlight(b)).join(\" or \")\n\t\t\t: highlight(\"your target branch\");\n\tp.log.success(\n\t\t`Push to ${branchList} to trigger your first translation run.`,\n\t);\n\tp.log.message(info(\" Docs: https://vocoder.app/docs/getting-started\"));\n}\n\n\nfunction writeApiKeyToEnv(apiKey: string): boolean {\n\tconst envPath = join(process.cwd(), \".env\");\n\tif (!existsSync(envPath)) return false;\n\n\ttry {\n\t\tconst content = readFileSync(envPath, \"utf-8\");\n\t\tconst keyLine = `VOCODER_API_KEY=${apiKey}`;\n\t\tlet updated: string;\n\n\t\tif (/^VOCODER_API_KEY=/m.test(content)) {\n\t\t\tupdated = content.replace(/^VOCODER_API_KEY=.*/m, keyLine);\n\t\t} else {\n\t\t\tconst sep = content.length > 0 && !content.endsWith(\"\\n\") ? \"\\n\" : \"\";\n\t\t\tupdated = `${content}${sep}${keyLine}\\n`;\n\t\t}\n\n\t\twriteFileSync(envPath, updated);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction printApiKey(apiKey: string): void {\n\tconst saved = writeApiKeyToEnv(apiKey);\n\n\tp.log.message(\"\");\n\tp.log.message(chalk.bold(\"Your API Key\"));\n\tprintCodeBlock(`VOCODER_API_KEY=${apiKey}`);\n\tif (saved) {\n\t\tp.log.success(chalk.dim(\"Saved to .env\"));\n\t} else {\n\t\tp.log.message(chalk.dim(\" Add the above to your .env file\"));\n\t}\n}\n\n// TODO: uncomment when @vocoder/mcp is published and functional\n// function printMcpSetup(apiKey: string): void {\n// \tconst addCommand = `claude mcp add --scope project --transport stdio \\\\\\n --env VOCODER_API_KEY=${apiKey} \\\\\\n vocoder -- npx -y @vocoder/mcp`;\n//\n// \tconst teamConfig = JSON.stringify(\n// \t\t{\n// \t\t\tmcpServers: {\n// \t\t\t\tvocoder: {\n// \t\t\t\t\ttype: \"stdio\",\n// \t\t\t\t\tcommand: \"npx\",\n// \t\t\t\t\targs: [\"-y\", \"@vocoder/mcp\"]\n// \t\t\t\t},\n// \t\t\t},\n// \t\t},\n// \t\tnull,\n// \t\t2,\n// \t);\n//\n// \tp.log.message(\"\");\n// \tp.log.message(chalk.bold(\"Use Vocoder with Claude Code\"));\n// \tp.log.message(\"\");\n// \tp.log.message(\"Run once to register the MCP server (embeds your key locally):\");\n// \tprintCodeBlock(addCommand);\n// \tp.log.message(\"\");\n// \tp.log.message(\n// \t\t\"To share with your team, commit \" +\n// \t\t\thighlight(\".mcp.json\") +\n// \t\t\t\" with an env var reference —\",\n// \t);\n// \tp.log.message(\n// \t\t\"each developer sets \" + highlight(\"VOCODER_API_KEY\") + \" in their own .env:\",\n// \t);\n// \tprintCodeBlock(teamConfig);\n// \tp.log.message(\"\");\n// \tp.log.message(chalk.gray(\"Docs: https://vocoder.app/docs/mcp\"));\n// }\n\nfunction printCodeBlock(code: string): void {\n\tconst lines = code.split(\"\\n\");\n\tconst maxLen = lines.reduce(\n\t\t(max: number, line: string) => Math.max(max, line.length),\n\t\t0,\n\t);\n\tconst bar = chalk.gray(\"│\");\n\tconst pad = (s: string) => s + \" \".repeat(maxLen - s.length);\n\n\tprocess.stdout.write(`${chalk.gray(\"│\")}\\n`);\n\tprocess.stdout.write(\n\t\t`${chalk.gray(\"│\")} ${chalk.gray(`┌${\"─\".repeat(maxLen + 2)}┐`)}\\n`,\n\t);\n\tfor (const line of lines) {\n\t\tprocess.stdout.write(`${chalk.gray(\"│\")} ${bar} ${pad(line)} ${bar}\\n`);\n\t}\n\tprocess.stdout.write(\n\t\t`${chalk.gray(\"│\")} ${chalk.gray(`└${\"─\".repeat(maxLen + 2)}┘`)}\\n`,\n\t);\n}\n\n// ── Auth helpers ─────────────────────────────────────────────────────────────\n\n\n\n/**\n * Run the browser authentication flow.\n * Returns `{ token, userInfo, organizationId? }` on success, or null if cancelled.\n * When `organizationId` is set, the GitHub App was installed in the same browser\n * trip — the caller should skip workspace selection and GitHub connect.\n *\n * @param reauth - When true, the user has an expired token and already has a workspace.\n * Use verificationUrl (auth/cli page) instead of installUrl so we don't create a\n * duplicate workspace. The direct-to-GitHub install URL is only for first-time setup.\n */\nasync function runAuthFlow(\n\tapi: VocoderAPI,\n\toptions: InitOptions,\n\treauth = false,\n\trepoCanonical?: string,\n): Promise<{\n\ttoken: string;\n\tuserId: string;\n\temail: string;\n\tname: string | null;\n\torganizationId?: string;\n\tdiscoveryReady?: boolean;\n} | null> {\n\t// Try to start a local callback server for instant token delivery.\n\t// In --ci mode the browser step is handled externally, so skip the callback\n\t// server and go straight to polling — simpler and testable.\n\tlet server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n\tif (!options.ci) {\n\t\ttry {\n\t\t\tserver = await startCallbackServer();\n\t\t} catch {\n\t\t\t// Port conflict or other issue — fall back to polling\n\t\t}\n\t}\n\n\tconst session = await api.startCliAuthSession(server?.port, repoCanonical);\n\t// Re-auth: user already has a workspace — use verificationUrl (auth/cli page)\n\t// so we don't trigger a new GitHub App install and create a duplicate workspace.\n\t// First-time: use installUrl to combine Vocoder auth + App install in one trip.\n\tconst browserUrl = reauth\n\t\t? session.verificationUrl\n\t\t: (session.installUrl ?? session.verificationUrl);\n\tconst expiresAt = new Date(session.expiresAt).getTime();\n\n\tif (options.ci) {\n\t\t// Machine-readable output for automated test harnesses.\n\t\t// Parsed by e2e/helpers/cli.ts: /^VOCODER_AUTH_URL: (.+)$/m\n\t\tprocess.stdout.write(`VOCODER_AUTH_URL: ${browserUrl}\\n`);\n\t\t// Also emit the session ID separately so tests can expire/complete sessions\n\t\tprocess.stdout.write(`VOCODER_SESSION_ID: ${session.sessionId}\\n`);\n\t} else if (\n\t\tprocess.stdin.isTTY &&\n\t\tprocess.stdout.isTTY &&\n\t\tprocess.env.CI !== \"true\"\n\t) {\n\t\tif (reauth) {\n\t\t\t// Re-auth: token expired, just sign in — no install choice needed\n\t\t\tif (!options.yes) {\n\t\t\t\tconst shouldOpen = await p.confirm({\n\t\t\t\t\tmessage: \"Open your browser to sign in again?\",\n\t\t\t\t});\n\t\t\t\tif (p.isCancel(shouldOpen)) {\n\t\t\t\t\tserver?.close();\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tif (!shouldOpen) {\n\t\t\t\t\tserver?.close();\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\tconst opened = await tryOpenBrowser(browserUrl);\n\t\t\t\t\tif (!opened) {\n\t\t\t\t\t\tp.note(browserUrl, \"Sign In\");\n\t\t\t\t\t\tp.log.info(\"Open the URL above manually to continue.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait tryOpenBrowser(browserUrl);\n\t\t\t}\n\t\t} else {\n\t\t\t// First-time setup: let user choose install vs link existing\n\t\t\tlet isLinkFlow = false;\n\t\t\tif (!options.yes) {\n\t\t\t\tconst connectChoice = await p.select<string>({\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"Vocoder needs to be installed on your GitHub account to get started\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"install\",\n\t\t\t\t\t\t\tlabel: \"Install GitHub App\",\n\t\t\t\t\t\t\thint: \"recommended\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ value: \"link\", label: \"Already installed? Link your account\" },\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tif (p.isCancel(connectChoice)) {\n\t\t\t\t\tserver?.close();\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tisLinkFlow = connectChoice === \"link\";\n\t\t\t}\n\n\t\t\t// For \"link\": get the OAuth-only URL from the server (no install page shown)\n\t\t\tlet urlToOpen = browserUrl;\n\t\t\tif (isLinkFlow) {\n\t\t\t\ttry {\n\t\t\t\t\tconst linkSession = await api.startCliGitHubLinkSession(\n\t\t\t\t\t\tsession.sessionId,\n\t\t\t\t\t\tserver?.port,\n\t\t\t\t\t);\n\t\t\t\t\turlToOpen = linkSession.oauthUrl;\n\t\t\t\t} catch {\n\t\t\t\t\t// Fall back to install URL if link-start fails\n\t\t\t\t\turlToOpen = browserUrl;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Open browser immediately — no separate confirm needed\n\t\t\tconst opened = await tryOpenBrowser(urlToOpen);\n\t\t\tif (!opened) {\n\t\t\t\t// Only show URL as a fallback if auto-open fails\n\t\t\t\tp.log.warn(\"Could not open your browser automatically.\");\n\t\t\t\tp.note(urlToOpen, \"GitHub\");\n\t\t\t\tp.log.info(\"Open the URL above to continue.\");\n\t\t\t}\n\t\t}\n\t}\n\n\tconst authSpinner = p.spinner();\n\tauthSpinner.start(\"Waiting for GitHub authorization...\");\n\n\tlet rawToken: string | null = null;\n\tlet callbackOrganizationId: string | undefined;\n\tlet callbackDiscoveryReady = false;\n\n\tif (server) {\n\t\t// Fast path: wait for the localhost callback\n\t\ttry {\n\t\t\tconst deadline = Math.min(expiresAt, Date.now() + 10 * 60 * 1000);\n\t\t\tconst timeoutMs = deadline - Date.now();\n\t\t\tconst params = await Promise.race([\n\t\t\t\tserver.waitForCallback(),\n\t\t\t\tnew Promise<null>((resolve) =>\n\t\t\t\t\tsetTimeout(() => resolve(null), timeoutMs),\n\t\t\t\t),\n\t\t\t]);\n\n\t\t\tif (params && typeof params.token === \"string\") {\n\t\t\t\trawToken = params.token;\n\t\t\t\tif (\n\t\t\t\t\ttypeof params.organizationId === \"string\" &&\n\t\t\t\t\tparams.organizationId\n\t\t\t\t) {\n\t\t\t\t\tcallbackOrganizationId = params.organizationId;\n\t\t\t\t}\n\t\t\t\t// Link flow: callback signals discovery results are cached\n\t\t\t\tif (params.discovery_ready === \"1\") {\n\t\t\t\t\tcallbackDiscoveryReady = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to polling\n\t\t} finally {\n\t\t\tserver.close();\n\t\t}\n\t}\n\n\tif (!rawToken) {\n\t\t// Polling fallback\n\t\twhile (Date.now() < expiresAt) {\n\t\t\tconst result = await api.pollCliAuthSession(session.sessionId);\n\n\t\t\tif (result.status === \"complete\") {\n\t\t\t\trawToken = result.token;\n\t\t\t\tif (result.organizationId) {\n\t\t\t\t\tcallbackOrganizationId = result.organizationId;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (result.status === \"failed\") {\n\t\t\t\tauthSpinner.stop();\n\t\t\t\tp.log.error(result.reason);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Still pending — wait 2s before next poll\n\t\t\tawait sleep(2000);\n\t\t}\n\t}\n\n\tif (!rawToken) {\n\t\tauthSpinner.stop();\n\t\tp.log.error(\"The authentication link expired. Run `vocoder init` again.\");\n\t\treturn null;\n\t}\n\n\t// Validate the token and get user info\n\tconst userInfo = await api.getCliUserInfo(rawToken);\n\tauthSpinner.stop(`Authenticated as ${chalk.bold(userInfo.email)}`);\n\n\treturn {\n\t\ttoken: rawToken,\n\t\t...userInfo,\n\t\torganizationId: callbackOrganizationId,\n\t\tdiscoveryReady: callbackDiscoveryReady,\n\t};\n}\n\n// ── Main command ─────────────────────────────────────────────────────────────\n\nexport async function init(options: InitOptions = {}): Promise<number> {\n\tconst apiUrl =\n\t\toptions.apiUrl || process.env.VOCODER_API_URL || \"https://vocoder.app\";\n\n\tp.intro(chalk.bold(\"Vocoder Setup\"));\n\n\ttry {\n\t\t// ── Detect git context ──────────────────────────────────────────────────\n\t\tconst gitContext = resolveGitContext();\n\t\tconst identity = gitContext.identity;\n\n\t\tif (gitContext.warnings.length > 0) {\n\t\t\tfor (const warning of gitContext.warnings) {\n\t\t\t\tp.log.warn(warning);\n\t\t\t}\n\t\t}\n\n\t\t// ── Fast lookup: does a project already exist for this repo? ────────────\n\t\t// No spinner — this is a fast DB read and we don't want an empty ◇ on miss.\n\t\tlet existingAppsForRepo: Array<{\n\t\t\tappDir: string;\n\t\t\tprojectId: string;\n\t\t\tprojectName: string;\n\t\t\torganizationName: string;\n\t\t}> = [];\n\t\tlet repoProjectId: string | null = null;\n\t\tlet repoProjectName: string | null = null;\n\n\t\tif (identity) {\n\t\t\tconst anonApi = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\t\t\tconst lookup = await anonApi.lookupAppByRepo({\n\t\t\t\trepoCanonical: identity.repoCanonical,\n\t\t\t\tappDir: identity.repoAppDir,\n\t\t\t});\n\n\t\t\t// Exact match: this scope is already configured.\n\t\t\tif (lookup.exactMatch) {\n\t\t\t\tconst { exactMatch } = lookup;\n\t\t\t\tp.log.success(`Project: ${chalk.bold(exactMatch.projectName)}`);\n\t\t\t\tp.log.info(\n\t\t\t\t\t`Branches: ${highlight((exactMatch.targetBranches ?? [\"main\"]).join(\", \"))}`,\n\t\t\t\t);\n\n\t\t\t\tconst needsKey = await p.confirm({\n\t\t\t\t\tmessage: \"Need to regenerate your API key?\",\n\t\t\t\t});\n\n\t\t\t\tif (!p.isCancel(needsKey) && needsKey) {\n\t\t\t\t\t// Auth required — run sign-in flow before generating key\n\t\t\t\t\tconst anonApi = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\t\t\t\t\tconst authResult = await runAuthFlow(\n\t\t\t\t\t\tanonApi,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\t/* reauth */ true,\n\t\t\t\t\t);\n\t\t\t\t\tif (!authResult) return 1;\n\n\t\t\t\t\tconst spinner = p.spinner();\n\t\t\t\t\tspinner.start(\"Generating new API key...\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { apiKey } = await anonApi.regenerateProjectApiKey(\n\t\t\t\t\t\t\tauthResult.token,\n\t\t\t\t\t\t\texactMatch.projectId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tspinner.stop(\"New API key generated\");\n\t\t\t\t\t\tprintApiKey(apiKey);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tspinner.stop(\"Failed to generate key\");\n\t\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tp.log.error(`Could not generate API key: ${msg}`);\n\t\t\t\t\t\tp.log.info(\"Try again or generate one from the dashboard.\");\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst isTs = detectLocalEcosystem().isTypeScript;\n\t\t\t\tconst written = writeVocoderConfig({ targetBranches: exactMatch.targetBranches ?? [\"main\"], useTypeScript: isTs });\n\t\t\t\tif (written) p.log.success(`Created ${highlight(written)}`);\n\t\t\t\tp.outro(\"Vocoder is already set up for this repository.\");\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\t// Whole-repo app exists: covers this repo from any directory — confirm and exit.\n\t\t\tif (lookup.hasWholeRepoApp) {\n\t\t\t\tconst wholeRepo = lookup.existingApps.find((a) => a.appDir === \"\");\n\t\t\t\tif (wholeRepo) {\n\t\t\t\t\tp.log.success(`Project: ${chalk.bold(wholeRepo.projectName)}`);\n\t\t\t\t\tconst isTs = detectLocalEcosystem().isTypeScript;\n\t\t\t\t\tconst written = writeVocoderConfig({ targetBranches: [\"main\"], useTypeScript: isTs });\n\t\t\t\t\tif (written) p.log.success(`Created ${highlight(written)}`);\n\t\t\t\t\tp.outro(\"Vocoder is already set up for this repository.\");\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Other scoped apps exist: this repo has a project but not for this scope.\n\t\t\t// Store for display + validation in the app directory prompt.\n\t\t\tif (lookup.existingApps.length > 0) {\n\t\t\t\texistingAppsForRepo = lookup.existingApps;\n\t\t\t\t// All apps belong to the same project (one project per repo)\n\t\t\t\trepoProjectId = lookup.existingApps[0]?.projectId ?? null;\n\t\t\t\trepoProjectName = lookup.existingApps[0]?.projectName ?? null;\n\t\t\t}\n\t\t}\n\n\t\t// ── Auth: check stored token, prompt if missing ─────────────────────────\n\t\tconst api = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\t\tlet userToken: string;\n\t\tlet userEmail: string;\n\t\tlet userName: string | null;\n\n\t\t// organizationId is set when auth+GitHub install completed in one browser trip\n\t\tlet authOrganizationId: string | undefined;\n\n\t\tconst storedAuth = await verifyStoredAuth(api);\n\n\t\t\tif (storedAuth.status === \"valid\") {\n\t\t\t\tp.log.success(`Authenticated as ${chalk.bold(storedAuth.email)}`);\n\t\t\t\tuserToken = storedAuth.token;\n\t\t\t\tuserEmail = storedAuth.email;\n\t\t\t\tuserName = storedAuth.name;\n\t\t\t} else {\n\t\t\t\t// \"gone\" = user deleted from DB → full first-time flow (installUrl)\n\t\t\t\t// \"expired\" = token rejected → reauth via verificationUrl (no new org)\n\t\t\t\t// \"none\" = no stored token → full first-time flow (installUrl)\n\t\t\t\tconst reauth = storedAuth.status === \"expired\";\n\t\t\t\tif (reauth) {\n\t\t\t\t\tp.log.warn(\"Stored credentials expired — signing in again\");\n\t\t\t\t} else if (storedAuth.status === \"gone\") {\n\t\t\t\t\tp.log.warn(\"Account not found — starting fresh setup\");\n\t\t\t\t}\n\t\t\t\tconst authResult = await runAuthFlow(\n\t\t\t\t\tapi,\n\t\t\t\t\toptions,\n\t\t\t\t\treauth,\n\t\t\t\t\tidentity?.repoCanonical,\n\t\t\t\t);\n\t\t\t\tif (!authResult) return 1;\n\t\t\t\tuserToken = authResult.token;\n\t\t\t\tuserEmail = authResult.email;\n\t\t\t\tuserName = authResult.name;\n\t\t\t\tauthOrganizationId = authResult.organizationId;\n\n\t\t\t\twriteAuthData({\n\t\t\t\t\ttoken: userToken,\n\t\t\t\t\tuserId: authResult.userId,\n\t\t\t\t\temail: userEmail,\n\t\t\t\t\tname: userName,\n\t\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\t});\n\t\t\t}\n\n\t\t// ── Workspace selection ─────────────────────────────────────────────────────\n\t\tlet selectedWorkspaceId: string;\n\t\tlet selectedWorkspaceName: string;\n\n\t\tif (authOrganizationId) {\n\t\t\t// Install path: auth+install completed in one browser trip, workspace already created.\n\t\t\tconst workspaceData = await api.listWorkspaces(userToken);\n\t\t\tconst ws = workspaceData.workspaces.find(\n\t\t\t\t(w) => w.id === authOrganizationId,\n\t\t\t);\n\t\t\tselectedWorkspaceId = authOrganizationId;\n\t\t\tselectedWorkspaceName = ws?.name ?? userEmail;\n\t\t\tp.log.success(\n\t\t\t\t`Connected as ${chalk.bold(userEmail)} — workspace: ${chalk.bold(selectedWorkspaceName)}`,\n\t\t\t);\n\t\t} else {\n\t\t\t// Always check for cached discovery results first. The cache expires in\n\t\t\t// 5 minutes so returning users (no recent link flow) fall through cleanly.\n\t\t\tconst discoveryResult = await api\n\t\t\t\t.getCliGitHubDiscovery(userToken)\n\t\t\t\t.catch(() => null);\n\t\t\tconst cachedInstallations = discoveryResult?.installations ?? [];\n\n\t\t\tif (cachedInstallations.length > 0) {\n\t\t\t\t// Warn if none of the discovered installations belong to the org that\n\t\t\t\t// owns the current repo — the binding won't be created even if setup succeeds.\n\t\t\t\tif (identity?.repoCanonical) {\n\t\t\t\t\tconst repoOwner = identity.repoCanonical\n\t\t\t\t\t\t.split(\":\")[1]\n\t\t\t\t\t\t?.split(\"/\")[0]\n\t\t\t\t\t\t?.toLowerCase();\n\t\t\t\t\tif (repoOwner) {\n\t\t\t\t\t\tconst hasMatchingAccount = cachedInstallations.some(\n\t\t\t\t\t\t\t(i) => i.accountLogin.toLowerCase() === repoOwner,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!hasMatchingAccount) {\n\t\t\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t\t\t`None of your GitHub App installations belong to \"${repoOwner}\", ` +\n\t\t\t\t\t\t\t\t\t`the account that owns this repository.\\n` +\n\t\t\t\t\t\t\t\t\t` The project will be created but translations won't trigger automatically.\\n` +\n\t\t\t\t\t\t\t\t\t` To fix: install the Vocoder GitHub App on \"${repoOwner}\" instead.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Auto-select when there's exactly one valid (non-suspended, unclaimed) installation\n\t\t\t\tconst validInstallations = cachedInstallations.filter(\n\t\t\t\t\t(i) => !i.isSuspended && !i.conflictLabel,\n\t\t\t\t);\n\n\t\t\t\tlet selectedInstallationId: number | string | null = null;\n\n\t\t\t\tif (\n\t\t\t\t\tvalidInstallations.length === 1 &&\n\t\t\t\t\tcachedInstallations.length === 1\n\t\t\t\t) {\n\t\t\t\t\t// Single installation — claim silently, no prompt needed\n\t\t\t\t\tselectedInstallationId = validInstallations[0]!.installationId;\n\t\t\t\t} else {\n\t\t\t\t\tselectedInstallationId = await selectGitHubInstallation(\n\t\t\t\t\t\tcachedInstallations.map((inst) => ({\n\t\t\t\t\t\t\tinstallationId: inst.installationId,\n\t\t\t\t\t\t\taccountLogin: inst.accountLogin,\n\t\t\t\t\t\t\taccountType: inst.accountType,\n\t\t\t\t\t\t\tisSuspended: inst.isSuspended,\n\t\t\t\t\t\t\tconflictLabel: inst.conflictLabel,\n\t\t\t\t\t\t})),\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tselectedInstallationId === null ||\n\t\t\t\t\tselectedInstallationId === \"install_new\"\n\t\t\t\t) {\n\t\t\t\t\tp.cancel(\n\t\t\t\t\t\t\"Setup cancelled. Re-run `vocoder init` and choose Install GitHub App.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tconst claimResult = await api.claimCliGitHubInstallation(userToken, {\n\t\t\t\t\tinstallationId: String(selectedInstallationId),\n\t\t\t\t\torganizationId: null,\n\t\t\t\t});\n\t\t\t\tselectedWorkspaceId = claimResult.organizationId;\n\t\t\t\tselectedWorkspaceName = claimResult.organizationName;\n\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t} else {\n\t\t\t\t// ── Repo-aware workspace resolution ──────────────────────────────────────\n\t\t\t\tconst workspaceData = await api.listWorkspaces(userToken, {\n\t\t\t\t\trepo: identity?.repoCanonical,\n\t\t\t\t});\n\n\t\t\t\tconst repoCanonical = identity?.repoCanonical ?? null;\n\t\t\t\t// Workspaces whose GitHub installation covers the current repo\n\t\t\t\tconst covering = repoCanonical\n\t\t\t\t\t? workspaceData.workspaces.filter((w) => w.coversRepo === true)\n\t\t\t\t\t: [];\n\t\t\t\t// Workspaces that have any GitHub connection (may not cover this repo)\n\t\t\t\tconst connected = workspaceData.workspaces.filter(\n\t\t\t\t\t(w) => w.hasGitHubConnection,\n\t\t\t\t);\n\n\t\t\t\tif (repoCanonical && covering.length === 1) {\n\t\t\t\t\t// ── Scenario 1: exactly one workspace covers this repo — auto-select ──\n\t\t\t\t\tconst ws = covering[0]!;\n\t\t\t\t\tselectedWorkspaceId = ws.id;\n\t\t\t\t\tselectedWorkspaceName = ws.name;\n\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t} else if (repoCanonical && covering.length > 1) {\n\t\t\t\t\t// ── Scenario 2: multiple workspaces cover this repo — let user pick ──\n\t\t\t\t\tconst choice = await p.select<string>({\n\t\t\t\t\t\tmessage: \"Select workspace for this repo\",\n\t\t\t\t\t\toptions: covering.map((w) => ({\n\t\t\t\t\t\t\tvalue: w.id,\n\t\t\t\t\t\t\tlabel: `${w.name} ${chalk.dim(`(${w.projectCount} project${w.projectCount !== 1 ? \"s\" : \"\"})`)}`,\n\t\t\t\t\t\t})),\n\t\t\t\t\t});\n\t\t\t\t\tif (p.isCancel(choice)) {\n\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\tconst ws = covering.find((w) => w.id === choice)!;\n\t\t\t\t\tselectedWorkspaceId = ws.id;\n\t\t\t\t\tselectedWorkspaceName = ws.name;\n\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t} else if (\n\t\t\t\t\trepoCanonical &&\n\t\t\t\t\tcovering.length === 0 &&\n\t\t\t\t\tconnected.length > 0\n\t\t\t\t) {\n\t\t\t\t\t// ── Scenario 3: connected workspaces exist but none cover this repo ──\n\t\t\t\t\tconst shortRepo = repoCanonical.split(\":\")[1] ?? repoCanonical;\n\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t`${chalk.bold(shortRepo)} isn't accessible from your Vocoder installation.\\n` +\n\t\t\t\t\t\t\t` Grant access to this repository or install on the account that owns it.`,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst fixOptions: Array<{ value: string; label: string }> = [];\n\t\t\t\t\tfor (const ws of connected) {\n\t\t\t\t\t\tif (ws.installationConfigureUrl) {\n\t\t\t\t\t\t\tfixOptions.push({\n\t\t\t\t\t\t\t\tvalue: `grant:${ws.id}`,\n\t\t\t\t\t\t\t\tlabel: `Configure ${chalk.bold(ws.connectionLabel ?? ws.name)}'s GitHub App installation`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfixOptions.push({\n\t\t\t\t\t\tvalue: \"install_new\",\n\t\t\t\t\t\tlabel: `Install on a different GitHub account ${chalk.dim(\"(creates a new personal workspace)\")}`,\n\t\t\t\t\t});\n\t\t\t\t\tfixOptions.push({ value: \"cancel\", label: \"Cancel\" });\n\n\t\t\t\t\tconst fix = await p.select<string>({\n\t\t\t\t\t\tmessage: \"How would you like to fix this?\",\n\t\t\t\t\t\toptions: fixOptions,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (p.isCancel(fix) || fix === \"cancel\") {\n\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (fix.startsWith(\"grant:\")) {\n\t\t\t\t\t\tconst ws = connected.find((w) => `grant:${w.id}` === fix)!;\n\t\t\t\t\t\tawait tryOpenBrowser(ws.installationConfigureUrl!);\n\t\t\t\t\t\tp.cancel(\n\t\t\t\t\t\t\t`Grant access to ${chalk.bold(shortRepo)} in your browser,\\n` +\n\t\t\t\t\t\t\t\t` then re-run ${chalk.bold(\"vocoder init\")}.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\n\t\t\t\t\t// install_new: full install → creates new workspace covering the new account\n\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\tapi,\n\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t});\n\t\t\t\t\tif (!connectResult) {\n\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\t\"GitHub App installation did not complete. Run `vocoder init` again.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t} else {\n\t\t\t\t\t// ── Fallback: no repo context or first-time user — standard select ────\n\t\t\t\t\tif (\n\t\t\t\t\t\tworkspaceData.workspaces.length === 1 &&\n\t\t\t\t\t\t!workspaceData.canCreateWorkspace\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst ws = workspaceData.workspaces[0]!;\n\t\t\t\t\t\tselectedWorkspaceId = ws.id;\n\t\t\t\t\t\tselectedWorkspaceName = ws.name;\n\t\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst workspaceResult = await selectWorkspace(workspaceData);\n\n\t\t\t\t\t\tif (workspaceResult.action === \"cancelled\") {\n\t\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (workspaceResult.action === \"use\") {\n\t\t\t\t\t\t\tselectedWorkspaceId = workspaceResult.workspace.id;\n\t\t\t\t\t\t\tselectedWorkspaceName = workspaceResult.workspace.name;\n\t\t\t\t\t\t\tp.log.success(`Workspace: ${chalk.bold(selectedWorkspaceName)}`);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// ── New workspace: GitHub connect flow ────────────────────────────────\n\t\t\t\t\t\t\tconst connectChoice = await p.select<string>({\n\t\t\t\t\t\t\t\tmessage: \"Connect your new workspace to GitHub\",\n\t\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t\t{ value: \"install\", label: \"Install the Vocoder GitHub App\" },\n\t\t\t\t\t\t\t\t\t{ value: \"link\", label: \"Link an existing installation\" },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (p.isCancel(connectChoice)) {\n\t\t\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (connectChoice === \"install\") {\n\t\t\t\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (!connectResult) {\n\t\t\t\t\t\t\t\t\tp.log.error(\n\t\t\t\t\t\t\t\t\t\t\"GitHub App installation did not complete. Run `vocoder init` again.\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\t\t\t\tp.log.success(\n\t\t\t\t\t\t\t\t\t`Workspace: ${chalk.bold(selectedWorkspaceName)}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst installations = await runGitHubDiscoveryFlow({\n\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tif (!installations) return 1;\n\n\t\t\t\t\t\t\t\tif (installations.length === 0) {\n\t\t\t\t\t\t\t\t\tp.log.warn(\n\t\t\t\t\t\t\t\t\t\t\"No GitHub installations found. Install the Vocoder GitHub App first.\",\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tconst installNow = await p.confirm({\n\t\t\t\t\t\t\t\t\t\tmessage: \"Open GitHub to install the App?\",\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (p.isCancel(installNow) || !installNow) return 1;\n\t\t\t\t\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tif (!connectResult) return 1;\n\t\t\t\t\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tconst selectedInstallationId = await selectGitHubInstallation(\n\t\t\t\t\t\t\t\t\t\tinstallations.map((inst) => ({\n\t\t\t\t\t\t\t\t\t\t\tinstallationId: inst.installationId,\n\t\t\t\t\t\t\t\t\t\t\taccountLogin: inst.accountLogin,\n\t\t\t\t\t\t\t\t\t\t\taccountType: inst.accountType,\n\t\t\t\t\t\t\t\t\t\t\tisSuspended: inst.isSuspended,\n\t\t\t\t\t\t\t\t\t\t\tconflictLabel: inst.conflictLabel,\n\t\t\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\tif (selectedInstallationId === null) {\n\t\t\t\t\t\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (selectedInstallationId === \"install_new\") {\n\t\t\t\t\t\t\t\t\t\tconst connectResult = await runGitHubInstallFlow({\n\t\t\t\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\t\t\tyes: options.yes,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tif (!connectResult) return 1;\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceId = connectResult.organizationId;\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceName = connectResult.organizationName;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst claimResult = await api.claimCliGitHubInstallation(\n\t\t\t\t\t\t\t\t\t\t\tuserToken,\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tinstallationId: String(selectedInstallationId),\n\t\t\t\t\t\t\t\t\t\t\t\torganizationId: null,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceId = claimResult.organizationId;\n\t\t\t\t\t\t\t\t\t\tselectedWorkspaceName = claimResult.organizationName;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tp.log.success(\n\t\t\t\t\t\t\t\t\t`Workspace: ${chalk.bold(selectedWorkspaceName)}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} // closes new workspace else\n\t\t\t\t\t} // closes auto-select else\n\t\t\t\t} // closes main scenario if/else chain\n\t\t\t} // closes cachedInstallations else\n\t\t} // closes if (authOrganizationId) else\n\n\t\t// ── Add-app path: repo already has a project with scoped apps ───────────────\n\t\t// Skip plan limit check — we're adding an App to an existing project,\n\t\t// not creating a new one. Run the project config prompts then call\n\t\t// POST /api/cli/project/apps.\n\t\tif (repoProjectId && repoProjectName && existingAppsForRepo.length > 0) {\n\t\t\tp.log.info(\n\t\t\t\t`${chalk.bold(repoProjectName)} is already set up for this repo.\\n` +\n\t\t\t\t\t` Configured apps: ${existingAppsForRepo\n\t\t\t\t\t\t.map((a) => highlight(a.appDir || \"(entire repo)\"))\n\t\t\t\t\t\t.join(\", \")}`,\n\t\t\t);\n\n\t\t\tconst appResult = await runAppCreate({\n\t\t\t\tapi,\n\t\t\t\tuserToken,\n\t\t\t\tprojectId: repoProjectId,\n\t\t\t\tprojectName: repoProjectName,\n\t\t\t\torganizationName: selectedWorkspaceName,\n\t\t\t\trepoCanonical: identity?.repoCanonical,\n\t\t\t\tdefaultAppDir: identity?.repoAppDir,\n\t\t\t\texistingApps: existingAppsForRepo,\n\t\t\t});\n\n\t\t\tif (!appResult) {\n\t\t\t\tp.log.error(\"App setup failed. Run `vocoder init` again.\");\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\trunScaffold({\n\t\t\t\tsourceLocale: appResult.sourceLocale,\n\t\t\t\ttargetBranches: appResult.targetBranches,\n\t\t\t\tappDir: identity?.repoAppDir,\n\t\t\t});\n\t\t\tp.outro(\"You're all set.\");\n\t\t\treturn 0;\n\t\t}\n\n\t\t// ── Plan limit pre-flight ────────────────────────────────────────────────────\n\t\ttry {\n\t\t\tconst wsCheck = await api.listWorkspaces(userToken);\n\t\t\tconst ws = wsCheck.workspaces.find((w) => w.id === selectedWorkspaceId);\n\t\t\tif (ws && ws.maxProjects !== -1 && ws.projectCount >= ws.maxProjects) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t`Project limit reached — ${ws.projectCount}/${ws.maxProjects} on your ${chalk.bold(ws.planId)} plan.`,\n\t\t\t\t);\n\n\t\t\t\t// \"Connect\" only makes sense when this repo already has a project\n\t\t\t\t// (found by the repo lookup above). Showing all workspace projects\n\t\t\t\t// would let users bind this repo to an unrelated project — invalid\n\t\t\t\t// given the 1:1 project↔repo coupling.\n\t\t\t\tconst options: Array<{ value: string; label: string }> = [];\n\t\t\t\tif (repoProjectId) {\n\t\t\t\t\toptions.push({\n\t\t\t\t\t\tvalue: \"connect\",\n\t\t\t\t\t\tlabel: `Reconnect this repo to ${chalk.bold(repoProjectName ?? \"existing project\")}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\toptions.push({ value: \"upgrade\", label: \"Upgrade plan\" });\n\t\t\t\toptions.push({ value: \"cancel\", label: \"Cancel\" });\n\n\t\t\t\tconst limitAction = await p.select<string>({\n\t\t\t\t\tmessage: \"What would you like to do?\",\n\t\t\t\t\toptions,\n\t\t\t\t});\n\n\t\t\t\tif (p.isCancel(limitAction) || limitAction === \"cancel\") {\n\t\t\t\t\tp.cancel(\"Setup cancelled.\");\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tif (limitAction === \"upgrade\") {\n\t\t\t\t\tawait tryOpenBrowser(`${apiUrl}${SUBSCRIPTION_SETTINGS_PATH}`);\n\t\t\t\t\tp.cancel(\n\t\t\t\t\t\t\"Upgrade your plan in the browser, then re-run `vocoder init`.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\t// connect: fetch existing project config and create App binding without\n\t\t\t\t// prompting — the project already owns sourceLocale/targetBranches.\n\t\t\t\tconst existingProjects = await api.listApps(\n\t\t\t\t\tuserToken,\n\t\t\t\t\tselectedWorkspaceId,\n\t\t\t\t);\n\t\t\t\tconst chosenProject = existingProjects.find(\n\t\t\t\t\t(proj) => proj.id === repoProjectId,\n\t\t\t\t);\n\t\t\t\tif (!chosenProject) {\n\t\t\t\t\tp.log.error(\"Could not find the project. Try again.\");\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst appResult = await api.createApp(userToken, {\n\t\t\t\t\t\tprojectId: chosenProject.id,\n\t\t\t\t\t\tappDir: identity?.repoAppDir ?? \"\",\n\t\t\t\t\t\tsourceLocale: chosenProject.sourceLocale,\n\t\t\t\t\t\ttargetLocales: chosenProject.targetLocales,\n\t\t\t\t\t\ttargetBranches: chosenProject.targetBranches,\n\t\t\t\t\t\trepoCanonical: identity?.repoCanonical ?? \"\",\n\t\t\t\t\t});\n\t\t\t\t\tp.log.success(`Connected to project: ${chalk.bold(chosenProject.name)}`);\n\t\t\t\t\tprintApiKey(appResult.apiKey);\n\t\t\t\t\trunScaffold({\n\t\t\t\t\t\tsourceLocale: chosenProject.sourceLocale,\n\t\t\t\t\t\ttargetBranches: chosenProject.targetBranches,\n\t\t\t\t\t\tappDir: identity?.repoAppDir,\n\t\t\t\t\t});\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\tp.log.error(`Failed to create app binding: ${msg}`);\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tp.outro(\"You're all set.\");\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Non-fatal\n\t\t}\n\n\t\t// ── Project configuration ────────────────────────────────────────────────────\n\t\tconst projectResult = await runProjectCreate({\n\t\t\tapi,\n\t\t\tuserToken,\n\t\t\torganizationId: selectedWorkspaceId,\n\t\t\tdefaultName: identity?.repoCanonical\n\t\t\t\t? identity.repoCanonical.split(\"/\").pop()\n\t\t\t\t: undefined,\n\t\t\tdefaultSourceLocale: \"en\",\n\t\t\trepoCanonical: identity?.repoCanonical,\n\t\t\tdefaultBranches: [\"main\"],\n\t\t\tdefaultAppDir: identity?.repoAppDir,\n\t\t});\n\n\t\tif (!projectResult) {\n\t\t\tp.log.error(\"Project creation failed. Run `vocoder init` again.\");\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Warn if the current repo isn't accessible to the GitHub App installation.\n\t\t// This means translations won't trigger on push until the App is granted access.\n\t\tif (!projectResult.repositoryBound && identity?.repoCanonical) {\n\t\t\tp.log.warn(\n\t\t\t\t`This repository isn't accessible to your GitHub App installation.\\n` +\n\t\t\t\t\t`Translations won't run automatically until you grant access.\\n\\n` +\n\t\t\t\t\t` To fix: go to your GitHub App installation settings and add this\\n` +\n\t\t\t\t\t` repository to the allowed list, or switch to \"All repositories\".\\n` +\n\t\t\t\t\t(projectResult.configureUrl\n\t\t\t\t\t\t? `\\n ${chalk.dim(projectResult.configureUrl)}\\n`\n\t\t\t\t\t\t: \"\"),\n\t\t\t);\n\t\t}\n\n\t\t// ── Scaffold + API key ───────────────────────────────────────────────────────\n\t\trunScaffold({\n\t\t\tsourceLocale: projectResult.sourceLocale,\n\t\t\ttargetBranches: projectResult.targetBranches,\n\t\t\tappDir: identity?.repoAppDir,\n\t\t});\n\n\t\tprintApiKey(projectResult.apiKey);\n\n\t\tp.outro(\"You're all set.\");\n\t\treturn 0;\n\t} catch (error) {\n\t\tif (error instanceof Error) {\n\t\t\tif (isPlanLimitFailure(error.message)) {\n\t\t\t\tprintPlanLimitMessage(apiUrl, error.message);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tp.log.error(`Error: ${error.message}`);\n\t\t} else {\n\t\t\tp.log.error(\"Unknown setup error\");\n\t\t}\n\n\t\treturn 1;\n\t}\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Returns the path of an existing vocoder.config file in cwd, trying\n * .ts → .js → .json in order. Returns null when none is found.\n */\nexport function findExistingConfig(cwd: string = process.cwd()): string | null {\n\tfor (const name of [\n\t\t\"vocoder.config.ts\",\n\t\t\"vocoder.config.js\",\n\t\t\"vocoder.config.json\",\n\t]) {\n\t\tconst candidate = join(cwd, name);\n\t\tif (existsSync(candidate)) return candidate;\n\t}\n\treturn null;\n}\n\n/**\n * Write a vocoder.config file to cwd if one doesn't already exist.\n * Pass `useTypeScript: false` for plain-JS projects — writes vocoder.config.js\n * instead of vocoder.config.ts. The config content is identical; only the\n * file extension (and therefore the import style in the user's editor) differs.\n *\n * Returns the filename that was written, or null if the file already existed\n * or the write failed.\n */\nexport function writeVocoderConfig(options: {\n\ttargetBranches?: string[];\n\tuseTypeScript?: boolean;\n\tcwd?: string;\n}): string | null {\n\tconst {\n\t\ttargetBranches = [\"main\"],\n\t\tuseTypeScript = true,\n\t\tcwd = process.cwd(),\n\t} = options;\n\n\t// Don't write if any config variant already exists\n\tif (findExistingConfig(cwd)) return null;\n\n\tconst ext = useTypeScript ? \"ts\" : \"js\";\n\tconst configPath = join(cwd, `vocoder.config.${ext}`);\n\tconst branchesStr = targetBranches.map((b) => `'${b}'`).join(\", \");\n\n\t// Patterns are always relative to the config file's own directory.\n\t// In a monorepo, the config lives in the app subdirectory, so `**` naturally\n\t// scopes to that app — no `appDir/` prefix needed (and adding it would break\n\t// extraction when the CLI or build plugin runs with the app dir as cwd).\n\tconst includes = [\"**/*.{tsx,jsx,ts,js}\"];\n\tconst includesStr = includes.map((p) => `'${p}'`).join(\", \");\n\n\t// Both TS and JS use ESM import syntax — the content is identical.\n\t// TypeScript users get type-checking from defineConfig; JS users get\n\t// the same runtime behaviour with no TS toolchain required.\n\tconst content = `import { defineConfig } from '@vocoder/config'\n\nexport default defineConfig({\n targetBranches: [${branchesStr}],\n include: [${includesStr}],\n})\n`;\n\n\ttry {\n\t\twriteFileSync(configPath, content, \"utf-8\");\n\t\treturn `vocoder.config.${ext}`;\n\t} catch {\n\t\treturn null;\n\t}\n}\n","import { spawn } from \"node:child_process\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport type { VocoderAPI } from \"./api.js\";\nimport { startCallbackServer } from \"./local-server.js\";\n\nasync function tryOpenBrowser(url: string): Promise<boolean> {\n\tif (!process.stdout.isTTY || process.env.CI === \"true\") {\n\t\treturn false;\n\t}\n\n\tconst platform = process.platform;\n\tlet command: string;\n\tlet args: string[];\n\n\tif (platform === \"darwin\") {\n\t\tcommand = \"open\";\n\t\targs = [url];\n\t} else if (platform === \"win32\") {\n\t\tcommand = \"rundll32\";\n\t\targs = [\"url.dll,FileProtocolHandler\", url];\n\t} else {\n\t\tcommand = \"xdg-open\";\n\t\targs = [url];\n\t}\n\n\treturn new Promise<boolean>((resolve) => {\n\t\ttry {\n\t\t\tconst child = spawn(command, args, {\n\t\t\t\tdetached: true,\n\t\t\t\tstdio: \"ignore\",\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\n\t\t\tlet settled = false;\n\t\t\tchild.once(\"spawn\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tchild.unref();\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t\tchild.once(\"error\", () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t});\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolve(false);\n\t\t\t}, 300);\n\t\t} catch {\n\t\t\tresolve(false);\n\t\t}\n\t});\n}\n\nexport interface GitHubConnectResult {\n\torganizationId: string;\n\torganizationName: string;\n\tconnectionLabel: string;\n}\n\n/**\n * Run the full GitHub App install flow for a new workspace.\n * Opens the browser to the GitHub App install page and waits for completion.\n *\n * Returns `null` if the user cancelled or an error occurred.\n */\nexport async function runGitHubInstallFlow(params: {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\torganizationId?: string;\n\tyes?: boolean;\n}): Promise<GitHubConnectResult | null> {\n\t// Try to start a local callback server for instant notification\n\tlet server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n\ttry {\n\t\tserver = await startCallbackServer();\n\t} catch {\n\t\t// Fall through — the user can re-run if something goes wrong\n\t}\n\n\tconst { installUrl } = await params.api.startCliGitHubInstall(\n\t\tparams.userToken,\n\t\t{\n\t\t\torganizationId: params.organizationId,\n\t\t\tcallbackPort: server?.port,\n\t\t},\n\t);\n\n\tp.log.info(\"Opening GitHub to install the Vocoder App...\");\n\tp.note(installUrl, \"Install URL\");\n\n\tif (\n\t\tprocess.stdin.isTTY &&\n\t\tprocess.stdout.isTTY &&\n\t\tprocess.env.CI !== \"true\"\n\t) {\n\t\tconst shouldOpen = params.yes\n\t\t\t? true\n\t\t\t: await p.confirm({ message: \"Open in your browser?\" });\n\n\t\tif (p.isCancel(shouldOpen)) {\n\t\t\tserver?.close();\n\t\t\treturn null;\n\t\t}\n\n\t\tif (shouldOpen) {\n\t\t\tconst opened = await tryOpenBrowser(installUrl);\n\t\t\tif (!opened) {\n\t\t\t\tp.log.info(\n\t\t\t\t\t\"Could not open a browser automatically. Use the URL above.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst connectSpinner = p.spinner();\n\tconnectSpinner.start(\"Waiting for GitHub App installation...\");\n\n\tif (server) {\n\t\ttry {\n\t\t\tconst params_timeout = 15 * 60 * 1000; // 15 minutes\n\t\t\tconst callbackParams = await Promise.race([\n\t\t\t\tserver.waitForCallback(),\n\t\t\t\tnew Promise<null>((resolve) =>\n\t\t\t\t\tsetTimeout(() => resolve(null), params_timeout),\n\t\t\t\t),\n\t\t\t]);\n\n\t\t\tserver.close();\n\n\t\t\tif (!callbackParams) {\n\t\t\t\tconnectSpinner.stop(\"GitHub App installation timed out\");\n\t\t\t\tp.log.error(\n\t\t\t\t\t\"The installation flow timed out. Run `vocoder init` again.\",\n\t\t\t\t);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (callbackParams.error) {\n\t\t\t\tconnectSpinner.stop(\"GitHub App installation failed\");\n\t\t\t\tp.log.error(callbackParams.error);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { organizationId, connectionLabel, workspace_created } =\n\t\t\t\tcallbackParams;\n\n\t\t\tif (!organizationId || !connectionLabel) {\n\t\t\t\tconnectSpinner.stop(\"GitHub App installation incomplete\");\n\t\t\t\tp.log.error(\"Missing organization or connection data from callback.\");\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconnectSpinner.stop(\n\t\t\t\t`Connected to GitHub as ${chalk.bold(connectionLabel)}`,\n\t\t\t);\n\n\t\t\t// Fetch the org name\n\t\t\tconst orgName = workspace_created ? connectionLabel : organizationId;\n\t\t\treturn {\n\t\t\t\torganizationId,\n\t\t\t\torganizationName: orgName,\n\t\t\t\tconnectionLabel,\n\t\t\t};\n\t\t} catch {\n\t\t\tserver.close();\n\t\t\tconnectSpinner.stop(\"GitHub App installation failed\");\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// No local server — there's no polling fallback for install; just wait\n\tconnectSpinner.stop(\"Could not detect GitHub App installation automatically\");\n\tp.log.warn(\n\t\t\"Complete the installation in your browser, then run `vocoder init` again.\",\n\t);\n\treturn null;\n}\n\n/**\n * Run the GitHub OAuth discovery flow to find existing installations.\n * Returns the list of installations with conflict labels, or null on cancellation/error.\n */\nexport async function runGitHubDiscoveryFlow(params: {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\torganizationId?: string;\n\tyes?: boolean;\n}): Promise<Array<{\n\tinstallationId: number;\n\taccountLogin: string;\n\taccountType: string;\n\tisSuspended: boolean;\n\tconflictLabel: string | null;\n}> | null> {\n\t// Try local callback server\n\tlet server: Awaited<ReturnType<typeof startCallbackServer>> | null = null;\n\ttry {\n\t\tserver = await startCallbackServer();\n\t} catch {\n\t\t// Fall through\n\t}\n\n\tconst { oauthUrl } = await params.api.startCliGitHubOAuth(params.userToken, {\n\t\torganizationId: params.organizationId,\n\t\tcallbackPort: server?.port,\n\t});\n\n\tp.log.info(\"Opening GitHub to authorize your account...\");\n\tp.note(\"Complete authorization in your browser.\");\n\n\tif (\n\t\tprocess.stdin.isTTY &&\n\t\tprocess.stdout.isTTY &&\n\t\tprocess.env.CI !== \"true\"\n\t) {\n\t\tconst shouldOpen = params.yes\n\t\t\t? true\n\t\t\t: await p.confirm({ message: \"Open in your browser?\" });\n\n\t\tif (p.isCancel(shouldOpen)) {\n\t\t\tserver?.close();\n\t\t\treturn null;\n\t\t}\n\n\t\tif (shouldOpen) {\n\t\t\tconst opened = await tryOpenBrowser(oauthUrl);\n\t\t\tif (!opened) {\n\t\t\t\tp.log.info(`Could not open browser automatically. Visit: ${oauthUrl}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst oauthSpinner = p.spinner();\n\toauthSpinner.start(\"Waiting for GitHub authorization...\");\n\n\tif (server) {\n\t\ttry {\n\t\t\tconst timeoutMs = 10 * 60 * 1000;\n\t\t\tconst callbackParams = await Promise.race([\n\t\t\t\tserver.waitForCallback(),\n\t\t\t\tnew Promise<null>((resolve) =>\n\t\t\t\t\tsetTimeout(() => resolve(null), timeoutMs),\n\t\t\t\t),\n\t\t\t]);\n\n\t\t\tserver.close();\n\n\t\t\tif (!callbackParams) {\n\t\t\t\toauthSpinner.stop(\"GitHub authorization timed out\");\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (callbackParams.error) {\n\t\t\t\toauthSpinner.stop(\"GitHub authorization failed\");\n\t\t\t\tp.log.error(callbackParams.error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} catch {\n\t\t\tserver.close();\n\t\t\toauthSpinner.stop(\"GitHub authorization failed\");\n\t\t\treturn null;\n\t\t}\n\t}\n\n\toauthSpinner.stop(\"GitHub account authorized\");\n\n\t// Fetch discovery results\n\tconst discoveryResult = await params.api.getCliGitHubDiscovery(\n\t\tparams.userToken,\n\t);\n\treturn discoveryResult.installations;\n}\n\ntype DiscoveredInstallation = {\n\tinstallationId: number;\n\taccountLogin: string;\n\taccountType: string;\n\tisSuspended: boolean;\n\tconflictLabel: string | null;\n};\n\n/**\n * Prompt the user to select a GitHub installation from discovery results.\n * Returns the selected installation ID, 'install_new' to trigger install flow,\n * or null on cancellation.\n */\nexport async function selectGitHubInstallation(\n\tinstallations: DiscoveredInstallation[],\n\tcanInstallNew: boolean,\n): Promise<number | \"install_new\" | null> {\n\ttype SelectValue = string;\n\n\tconst options: Array<{ value: SelectValue; label: string; hint?: string }> =\n\t\tinstallations.map((inst) => ({\n\t\t\tvalue: String(inst.installationId),\n\t\t\tlabel: inst.accountLogin,\n\t\t\thint:\n\t\t\t\t[\n\t\t\t\t\tinst.accountType === \"Organization\" ? \"organization\" : \"personal\",\n\t\t\t\t\tinst.conflictLabel ? `connected to ${inst.conflictLabel}` : \"\",\n\t\t\t\t\tinst.isSuspended ? \"suspended\" : \"\",\n\t\t\t\t]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join(\" · \") || undefined,\n\t\t}));\n\n\tif (canInstallNew) {\n\t\toptions.push({\n\t\t\tvalue: \"install_new\",\n\t\t\tlabel: `Install on a new account ${chalk.dim(\"(creates a new personal workspace)\")}`,\n\t\t});\n\t}\n\n\tconst selected = await p.select<SelectValue>({\n\t\tmessage: \"Select a GitHub installation\",\n\t\toptions,\n\t});\n\n\tif (p.isCancel(selected)) return null;\n\tif (selected === \"install_new\") return \"install_new\";\n\n\treturn Number(selected);\n}\n","import { createServer } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { URL } from \"node:url\";\n\nexport interface LocalServerHandle {\n\tport: number;\n\twaitForCallback: () => Promise<Record<string, string>>;\n\tclose: () => void;\n}\n\n/**\n * Starts a local HTTP server on a random available port.\n * Returns the port and a promise that resolves when the browser\n * redirects to /callback with query parameters.\n *\n * Used for the browser→CLI token handoff pattern:\n * 1. CLI passes `port` to the auth session start request\n * 2. After browser auth, vocoder.app redirects to localhost:<port>/callback?token=...\n * 3. `waitForCallback()` resolves with the query params\n */\nexport function startCallbackServer(): Promise<LocalServerHandle> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tlet callbackResolve: ((params: Record<string, string>) => void) | null =\n\t\t\tnull;\n\t\tlet callbackReject: ((err: Error) => void) | null = null;\n\n\t\tconst callbackPromise = new Promise<Record<string, string>>((res, rej) => {\n\t\t\tcallbackResolve = res;\n\t\t\tcallbackReject = rej;\n\t\t});\n\n\t\tconst server = createServer((req, res) => {\n\t\t\tif (!req.url) {\n\t\t\t\tres.writeHead(400);\n\t\t\t\tres.end();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet pathname: string;\n\t\t\tlet params: Record<string, string>;\n\n\t\t\ttry {\n\t\t\t\tconst parsed = new URL(req.url, \"http://localhost\");\n\t\t\t\tpathname = parsed.pathname;\n\t\t\t\tparams = Object.fromEntries(parsed.searchParams.entries());\n\t\t\t} catch {\n\t\t\t\tres.writeHead(400);\n\t\t\t\tres.end(\"Bad request\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (pathname !== \"/callback\") {\n\t\t\t\tres.writeHead(404);\n\t\t\t\tres.end(\"Not found\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tres.writeHead(200, { \"Content-Type\": \"text/html\" });\n\t\t\tres.end(\n\t\t\t\t\"<!DOCTYPE html><html><head><title>Authenticated</title></head>\" +\n\t\t\t\t\t'<body style=\"font-family:sans-serif;text-align:center;padding:3rem;\">' +\n\t\t\t\t\t\"<h2>Authenticated</h2>\" +\n\t\t\t\t\t\"<p>Return to your terminal to continue. You can close this tab.</p>\" +\n\t\t\t\t\t\"</body></html>\",\n\t\t\t);\n\n\t\t\tif (callbackResolve) {\n\t\t\t\tcallbackResolve(params);\n\t\t\t\tcallbackResolve = null;\n\t\t\t}\n\n\t\t\tsetImmediate(() => server.close());\n\t\t});\n\n\t\tserver.on(\"error\", (err) => {\n\t\t\tif (!settled) {\n\t\t\t\tsettled = true;\n\t\t\t\tif (callbackReject) callbackReject(err);\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\n\t\t// Bind to a random port on localhost only\n\t\tserver.listen(0, \"127.0.0.1\", () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\n\t\t\tconst port = (server.address() as AddressInfo).port;\n\n\t\t\tresolve({\n\t\t\t\tport,\n\t\t\t\twaitForCallback: () => callbackPromise,\n\t\t\t\tclose: () => server.close(),\n\t\t\t});\n\t\t});\n\t});\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport type { VocoderAPI } from \"./api.js\";\nimport { detectGitBranches, filterableBranchSelect } from \"./branch-select.js\";\nimport type { LocaleOption } from \"./locale-search.js\";\nimport {\n\tsearchMultiSelectLocales,\n\tsearchSelectLocale,\n} from \"./locale-search.js\";\n\nexport interface ExistingApp {\n\tappDir: string;\n\tprojectId: string;\n\tprojectName: string;\n\torganizationName: string;\n}\n\nexport interface ProjectCreateParams {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\torganizationId: string;\n\t/** Default project name (repo name or directory name) */\n\tdefaultName?: string;\n\t/** Pre-detected source locale, e.g. \"en\" */\n\tdefaultSourceLocale?: string;\n\t/** Repo canonical for binding the project, e.g. \"github:owner/repo\" */\n\trepoCanonical?: string;\n\t/** Default target branches */\n\tdefaultBranches?: string[];\n\t/**\n\t * Auto-detected scope path (CWD relative to git root).\n\t * Non-empty when running from a subdirectory of the repo — monorepo use case.\n\t * e.g. \"apps/web\"\n\t */\n\tdefaultAppDir?: string;\n}\n\nexport interface AppCreateParams {\n\tapi: VocoderAPI;\n\tuserToken: string;\n\tprojectId: string;\n\tprojectName: string;\n\torganizationName: string;\n\trepoCanonical?: string;\n\tdefaultAppDir?: string;\n\t/** Existing apps to display and validate against */\n\texistingApps: ExistingApp[];\n}\n\nexport interface AppCreateResult {\n\tprojectId: string;\n\tprojectName: string;\n\tapiKey: string;\n\tappDir: string;\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\ttargetBranches: string[];\n}\n\nexport interface ProjectCreateResult {\n\tprojectId: string;\n\tprojectName: string;\n\tapiKey: string;\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\ttargetBranches: string[];\n\trepositoryBound: boolean;\n\tconfigureUrl?: string;\n}\n\n/** All locales — used for target language selection. */\nfunction buildLocaleOptions(\n\tlocales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n\treturn locales.map((l) => ({\n\t\tbcp47: l.code,\n\t\tlabel: `${l.name} — ${l.code}`,\n\t}));\n}\n\n/**\n * Deduplicated language list — used for source language selection.\n * Groups locales by language family (prefix before first hyphen) and keeps one\n * representative per family, preferring the shortest/base code (e.g. \"en\" over\n * \"en-US\"). This prevents showing \"English\", \"English (American)\", \"English\n * (British)\" as three separate choices when the user just means \"English\".\n */\nfunction buildLanguageOptions(\n\tlocales: Array<{ code: string; name: string; nativeName?: string }>,\n): LocaleOption[] {\n\tconst byFamily = new Map<string, LocaleOption>();\n\n\tfor (const l of locales) {\n\t\tconst family = l.code.split(\"-\")[0]!.toLowerCase();\n\t\tconst opt: LocaleOption = { bcp47: l.code, label: `${l.name} — ${l.code}` };\n\t\tconst existing = byFamily.get(family);\n\t\t// Prefer base code (shorter, no region suffix) over regional variants\n\t\tif (!existing || l.code.length < existing.bcp47.length) {\n\t\t\tbyFamily.set(family, opt);\n\t\t}\n\t}\n\n\treturn Array.from(byFamily.values());\n}\n\n/**\n * Run the full project configuration TUI: prompts for name, source locale,\n * target locales, and target branches, then calls POST /api/cli/projects.\n *\n * Returns the created project info (including API key), or null if cancelled.\n */\nexport async function runProjectCreate(\n\tparams: ProjectCreateParams,\n): Promise<ProjectCreateResult | null> {\n\tconst { api, userToken, organizationId, repoCanonical } = params;\n\n\t// ── Project name ────────────────────────────────────────────────────────────\n\t// Use the detected repo name automatically — no prompt needed.\n\tconst projectName = (params.defaultName ?? \"my-project\").trim();\n\tp.log.success(`Project: ${chalk.bold(projectName)}`);\n\n\t// ── Fetch source locales ────────────────────────────────────────────────────\n\tlet sourceLocales: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\t({ sourceLocales } = await api.listLocales(userToken));\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch supported locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst languageOptions = buildLanguageOptions(sourceLocales);\n\n\t// ── Scope path (monorepo) ───────────────────────────────────────────────────\n\tconst appDir = params.defaultAppDir ?? \"\";\n\tif (appDir) {\n\t\tp.log.success(`App directory: ${chalk.bold(appDir)}`);\n\t}\n\n\t// ── Source locale ───────────────────────────────────────────────────────────\n\tconst sourceLocale = await searchSelectLocale(\n\t\tlanguageOptions,\n\t\t\"Source language (the language your code is written in)\",\n\t\tparams.defaultSourceLocale ?? \"en\",\n\t);\n\n\tif (sourceLocale === null) return null;\n\n\t// ── Compatible target locales (fetched after source is known) ───────────────\n\tlet compatibleTargets: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\tcompatibleTargets = await api.listCompatibleLocales(userToken, sourceLocale);\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch compatible target locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst localeOptions = buildLocaleOptions(compatibleTargets);\n\n\t// ── Target locales ──────────────────────────────────────────────────────────\n\tconst targetOptions = localeOptions.filter(\n\t\t(opt) => opt.bcp47 !== sourceLocale,\n\t);\n\n\tconst targetLocales = await searchMultiSelectLocales(\n\t\ttargetOptions,\n\t\t\"Target languages (languages to translate into)\",\n\t);\n\n\tif (targetLocales === null) return null;\n\n\tif (targetLocales.length === 0) {\n\t\tp.log.warn(\n\t\t\t\"No target languages selected — you can add them later from the dashboard.\",\n\t\t);\n\t}\n\n\t// ── Branch triggers — per-trigger selection ────────────────────────────────\n\t// Ask which branches should fire for each trigger type. Branches can appear\n\t// in both push and PR (they get both triggers). Manual is mutually exclusive:\n\t// a branch cannot be both automatic (push/PR) and manual-only.\n\tconst detected = detectGitBranches();\n\tconst initialBranches = params.defaultBranches?.length\n\t\t? params.defaultBranches\n\t\t: [detected.defaultBranch];\n\n\t// Step 1: push (required)\n\tlet pushBranches: string[] = [];\n\t{\n\t\tlet initial = initialBranches;\n\t\twhile (pushBranches.length === 0) {\n\t\t\tconst result = await filterableBranchSelect({\n\t\t\t\tmessage: \"Which branches should trigger translations?\",\n\t\t\t\tbranches: detected.branches,\n\t\t\t\tdefaultBranch: detected.defaultBranch,\n\t\t\t\tinitialValues: initial,\n\t\t\t});\n\t\t\tif (result === null) return null;\n\t\t\tif (result.length === 0) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t\"At least one branch is required. Please select at least one.\",\n\t\t\t\t);\n\t\t\t\tinitial = [detected.defaultBranch];\n\t\t\t} else {\n\t\t\t\tpushBranches = result;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst targetBranches = pushBranches;\n\n\t// ── Create project ──────────────────────────────────────────────────────────\n\ttry {\n\t\tconst result = await api.createProject(userToken, {\n\t\t\torganizationId,\n\t\t\tname: projectName,\n\t\t\tsourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t\tappDirs: appDir ? [appDir] : [],\n\t\t\trepoCanonical,\n\t\t});\n\n\t\tp.log.success(`Project ${chalk.bold(result.projectName)} created!`);\n\t\treturn result;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"Unknown error\";\n\t\tp.log.error(`Failed to create project: ${message}`);\n\t\treturn null;\n\t}\n}\n\n/**\n * Configure and create a new App under an existing project.\n * Used when the repo already has a project (monorepo: adding a new app directory).\n * No plan limit check runs — only a new App is created, not a new Project.\n */\nexport async function runAppCreate(\n\tparams: AppCreateParams,\n): Promise<AppCreateResult | null> {\n\tconst { api, userToken, projectId, projectName, repoCanonical } = params;\n\tconst existingScopes = new Set(params.existingApps.map((a) => a.appDir));\n\n\t// ── Fetch source locales ────────────────────────────────────────────────────\n\tlet sourceLocales: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\t({ sourceLocales } = await api.listLocales(userToken));\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch supported locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst languageOptions = buildLanguageOptions(sourceLocales);\n\n\t// ── App directory ───────────────────────────────────────────────────────────\n\tconst appDir = params.defaultAppDir ?? \"\";\n\tif (existingScopes.has(appDir)) {\n\t\tp.log.error(`App directory \"${appDir}\" is already configured for this project.`);\n\t\treturn null;\n\t}\n\tif (appDir) {\n\t\tp.log.success(`App directory: ${chalk.bold(appDir)}`);\n\t}\n\n\t// ── Source locale ───────────────────────────────────────────────────────────\n\tconst sourceLocale = await searchSelectLocale(\n\t\tlanguageOptions,\n\t\t\"Source language\",\n\t\t\"en\",\n\t);\n\tif (sourceLocale === null) return null;\n\n\t// ── Compatible target locales (fetched after source is known) ───────────────\n\tlet compatibleTargets: Array<{ code: string; name: string; nativeName?: string }>;\n\ttry {\n\t\tcompatibleTargets = await api.listCompatibleLocales(userToken, sourceLocale);\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Failed to fetch compatible target locales. Check your connection and try again.\",\n\t\t);\n\t\treturn null;\n\t}\n\n\t// ── Target locales ──────────────────────────────────────────────────────────\n\tconst targetOptions = buildLocaleOptions(compatibleTargets).filter(\n\t\t(opt) => opt.bcp47 !== sourceLocale,\n\t);\n\tconst targetLocales = await searchMultiSelectLocales(\n\t\ttargetOptions,\n\t\t\"Target languages\",\n\t);\n\tif (targetLocales === null) return null;\n\tif (targetLocales.length === 0) {\n\t\tp.log.warn(\n\t\t\t\"No target languages selected — you can add them later from the dashboard.\",\n\t\t);\n\t}\n\n\t// ── Branch triggers — per-trigger selection (same logic as runProjectCreate) ─\n\tconst detectedApp = detectGitBranches();\n\n\tlet appPushBranches: string[] = [];\n\t{\n\t\tlet initial = [detectedApp.defaultBranch];\n\t\twhile (appPushBranches.length === 0) {\n\t\t\tconst result = await filterableBranchSelect({\n\t\t\t\tmessage: \"Which branches should trigger translations?\",\n\t\t\t\tbranches: detectedApp.branches,\n\t\t\t\tdefaultBranch: detectedApp.defaultBranch,\n\t\t\t\tinitialValues: initial,\n\t\t\t});\n\t\t\tif (result === null) return null;\n\t\t\tif (result.length === 0) {\n\t\t\t\tp.log.warn(\"At least one branch is required.\");\n\t\t\t\tinitial = [detectedApp.defaultBranch];\n\t\t\t} else {\n\t\t\t\tappPushBranches = result;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst targetBranches = appPushBranches;\n\n\t// ── Create the App ─────────────────────────────────────────────────────────\n\ttry {\n\t\tconst result = await api.createProject(userToken, {\n\t\t\tprojectId,\n\t\t\tappDir,\n\t\t\tsourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t\trepoCanonical: repoCanonical ?? \"\",\n\t\t});\n\n\t\tp.log.success(\n\t\t\t`App ${chalk.bold(appDir)} added to ${chalk.bold(projectName)}!`,\n\t\t);\n\t\treturn {\n\t\t\tprojectId: result.projectId,\n\t\t\tprojectName: result.projectName,\n\t\t\tapiKey: result.apiKey,\n\t\t\tappDir: result.appDir,\n\t\t\tsourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t};\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"Unknown error\";\n\t\tp.log.error(`Failed to add app: ${message}`);\n\t\treturn null;\n\t}\n}\n","import { execSync } from \"node:child_process\";\nimport { isCancel, Prompt } from \"@clack/core\";\nimport { active, bld, dim, grn, info, red, ylw } from \"./theme.js\";\n\n// ── Symbols ───────────────────────────────────────────────────────────────────\n\nconst S_BAR = \"│\";\nconst S_BAR_END = \"└\";\nconst S_ACTIVE = \"◆\";\nconst S_SUBMIT = \"◆\";\nconst S_CANCEL = \"■\";\nconst S_ERROR = \"▲\";\n\nfunction symbol(state: string): string {\n\tswitch (state) {\n\t\tcase \"submit\":\n\t\t\treturn grn(S_SUBMIT);\n\t\tcase \"cancel\":\n\t\t\treturn red(S_CANCEL);\n\t\tcase \"error\":\n\t\t\treturn ylw(S_ERROR);\n\t\tdefault:\n\t\t\treturn active(S_ACTIVE);\n\t}\n}\n\n// ── Git detection ─────────────────────────────────────────────────────────────\n\nexport interface DetectedBranches {\n\tbranches: string[];\n\tdefaultBranch: string;\n}\n\nexport function detectGitBranches(cwd?: string): DetectedBranches {\n\tconst workDir = cwd ?? process.cwd();\n\ttry {\n\t\t// Local branches\n\t\tconst localOut = execSync(\"git branch\", {\n\t\t\tcwd: workDir,\n\t\t\tstdio: \"pipe\",\n\t\t}).toString();\n\t\tconst localBranches = localOut\n\t\t\t.split(\"\\n\")\n\t\t\t.filter(Boolean)\n\t\t\t.map((b) => b.replace(/^\\*?\\s*/, \"\").trim())\n\t\t\t.filter(Boolean);\n\n\t\t// Remote branches (strip \"origin/\" prefix, skip HEAD pointer)\n\t\tlet remoteBranches: string[] = [];\n\t\ttry {\n\t\t\tconst remoteOut = execSync(\"git branch -r\", {\n\t\t\t\tcwd: workDir,\n\t\t\t\tstdio: \"pipe\",\n\t\t\t}).toString();\n\t\t\tremoteBranches = remoteOut\n\t\t\t\t.split(\"\\n\")\n\t\t\t\t.map((b) => b.trim())\n\t\t\t\t.filter((b) => b && !b.includes(\"HEAD\"))\n\t\t\t\t.map((b) => b.replace(/^[^/]+\\//, \"\")); // strip \"origin/\" (or any remote name)\n\t\t} catch {\n\t\t\t/* no remote */\n\t\t}\n\n\t\tconst branches = [...new Set([...localBranches, ...remoteBranches])].sort();\n\n\t\t// Default branch: ask git for origin's HEAD (local cache, no network call).\n\t\t// Falls back to 'main' if the remote HEAD isn't cached.\n\t\tlet defaultBranch = \"main\";\n\t\ttry {\n\t\t\tconst ref = execSync(\"git symbolic-ref refs/remotes/origin/HEAD\", {\n\t\t\t\tcwd: workDir,\n\t\t\t\tstdio: \"pipe\",\n\t\t\t})\n\t\t\t\t.toString()\n\t\t\t\t.trim();\n\t\t\t// ref = \"refs/remotes/origin/main\"\n\t\t\tdefaultBranch = ref.split(\"/\").pop() ?? \"main\";\n\t\t} catch {\n\t\t\t/* HEAD not cached — run \"git remote set-head origin --auto\" to fix */\n\t\t}\n\n\t\treturn {\n\t\t\tbranches: branches.length > 0 ? branches : [defaultBranch],\n\t\t\tdefaultBranch,\n\t\t};\n\t} catch {\n\t\treturn { branches: [\"main\"], defaultBranch: \"main\" };\n\t}\n}\n\n// ── Validation ────────────────────────────────────────────────────────────────\n\nconst INVALID_CHARS = /[\\s?^~:[\\]\\\\]/;\n\nexport function validateBranchPattern(pattern: string): string | null {\n\tconst t = pattern.trim();\n\tif (!t) return \"Pattern cannot be empty\";\n\tif (INVALID_CHARS.test(t))\n\t\treturn \"Invalid characters — avoid spaces, ?, ^, ~, :, [, ], \\\\\";\n\tif (t.startsWith(\"/\") || t.endsWith(\"/\")) return \"Cannot start or end with /\";\n\tif (t.includes(\"//\")) return \"Cannot contain //\";\n\treturn null;\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 10;\nconst _ADD_PATTERN_VALUE = \"__add__\";\n\ninterface BranchItem {\n\tvalue: string;\n\tlabel: string;\n\tisCustom?: boolean;\n}\n\nfunction buildItems(\n\tbranches: string[],\n\tdefaultBranch: string,\n\tcustomPatterns: string[],\n): BranchItem[] {\n\tconst items: BranchItem[] = branches.map((b) => ({\n\t\tvalue: b,\n\t\tlabel: b === defaultBranch ? `${b} (default branch)` : b,\n\t}));\n\tfor (const pt of customPatterns) {\n\t\tif (!branches.includes(pt)) {\n\t\t\titems.push({ value: pt, label: pt, isCustom: true });\n\t\t}\n\t}\n\treturn items;\n}\n\nfunction filterItems(items: BranchItem[], query: string): BranchItem[] {\n\tif (!query.trim()) return items;\n\tconst lower = query.toLowerCase();\n\treturn items.filter((i) => i.value.toLowerCase().includes(lower));\n}\n\nfunction buildList(\n\tfiltered: BranchItem[],\n\tcursor: number,\n\tscrollOffset: number,\n\tselected: Set<string>,\n\tfilter: string,\n\tcustomPatterns: string[],\n\taddCursor: boolean,\n\toptional = false,\n\texcludedPatterns: Set<string> = new Set(),\n): string {\n\tconst lines: string[] = [];\n\tconst end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n\n\tfor (let i = scrollOffset; i < end; i++) {\n\t\tconst item = filtered[i]!;\n\t\tconst isCursor = i === cursor && !addCursor;\n\t\tconst isChecked = selected.has(item.value);\n\n\t\tconst icon = isChecked\n\t\t\t? isCursor\n\t\t\t\t? info(\"◼\")\n\t\t\t\t: info(\"◼\")\n\t\t\t: isCursor\n\t\t\t\t? active(\"◻\")\n\t\t\t\t: dim(\"◻\");\n\n\t\tlet label = item.isCustom ? `${item.label} ${dim(\"(custom)\")}` : item.label;\n\t\tif (isCursor) label = bld(label);\n\n\t\tlines.push(`${info(S_BAR)} ${icon} ${label}`);\n\t}\n\n\t// \"Add pattern\" option\n\tconst trimmed = filter.trim();\n\tconst allItems = [...filtered]; // simplified: just check filtered\n\tconst isNewPattern =\n\t\ttrimmed.length > 0 &&\n\t\t!allItems.some((i) => i.value === trimmed) &&\n\t\t!customPatterns.includes(trimmed);\n\n\tif (isNewPattern) {\n\t\tconst err =\n\t\t\tvalidateBranchPattern(trimmed) ??\n\t\t\t(excludedPatterns.has(trimmed)\n\t\t\t\t? \"Already used for automatic translation\"\n\t\t\t\t: null);\n\t\tconst icon = addCursor ? active(\"◻\") : dim(\"◻\");\n\t\tconst label = err\n\t\t\t? `${ylw(\"+\")} ${dim(`\"${trimmed}\" — ${err}`)}`\n\t\t\t: `${grn(\"+\")} Add \"${trimmed}\" as branch pattern`;\n\t\tlines.push(`${info(S_BAR)} ${icon} ${label}`);\n\t} else if (filtered.length === 0 && trimmed.length === 0) {\n\t\tlines.push(dim(`${S_BAR} No branches detected`));\n\t}\n\n\tconst hidden = filtered.length - (end - scrollOffset);\n\tif (hidden > 0) lines.push(dim(`${S_BAR} ${hidden} more`));\n\tif (selected.size > 0) {\n\t\tlines.push(dim(`${S_BAR} ${selected.size} selected — Enter to confirm`));\n\t} else if (optional) {\n\t\tlines.push(dim(`${S_BAR} Enter to skip`));\n\t}\n\n\treturn lines.join(\"\\n\");\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport async function filterableBranchSelect(params: {\n\tmessage: string;\n\tbranches: string[];\n\tdefaultBranch: string;\n\tinitialValues?: string[];\n\t/** When true, empty selection is accepted (Enter = skip) */\n\toptional?: boolean;\n\t/** Branches already claimed by other trigger types — block custom entry of these */\n\texcludedPatterns?: string[];\n}): Promise<string[] | null> {\n\tconst { message, branches, defaultBranch } = params;\n\tconst optional = params.optional ?? false;\n\tconst excludedSet = new Set(params.excludedPatterns ?? []);\n\n\tlet filter = \"\";\n\tlet cursor = 0;\n\tlet scrollOffset = 0;\n\tlet addCursor = false;\n\tconst customPatterns: string[] = [];\n\tconst selected = new Set<string>(params.initialValues ?? [defaultBranch]);\n\n\tconst getItems = () => buildItems(branches, defaultBranch, customPatterns);\n\tconst getFiltered = () => filterItems(getItems(), filter);\n\n\tconst isNewPattern = () => {\n\t\tconst t = filter.trim();\n\t\tif (!t) return false;\n\t\treturn (\n\t\t\t!getItems().some((i) => i.value === t) && !customPatterns.includes(t)\n\t\t);\n\t};\n\n\tconst clampCursor = (filtered: BranchItem[]) => {\n\t\tconst hasAdd = isNewPattern();\n\t\tconst max = filtered.length - 1 + (hasAdd ? 1 : 0);\n\t\tif (cursor > max && !addCursor) cursor = Math.max(0, max);\n\t\tif (!addCursor) {\n\t\t\tif (cursor < scrollOffset) scrollOffset = cursor;\n\t\t\tif (cursor >= scrollOffset + MAX_VISIBLE)\n\t\t\t\tscrollOffset = cursor - MAX_VISIBLE + 1;\n\t\t\tif (scrollOffset < 0) scrollOffset = 0;\n\t\t}\n\t};\n\n\tconst prompt = new (Prompt as any)(\n\t\t{\n\t\t\tvalidate() {\n\t\t\t\tif (!optional && selected.size === 0)\n\t\t\t\t\treturn \"At least one branch is required.\";\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\trender(this: { state: string; error: string }) {\n\t\t\t\tconst filtered = getFiltered();\n\t\t\t\tclampCursor(filtered);\n\n\t\t\t\tconst hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n\t\t\t\tconst hint =\n\t\t\t\t\tfilter.length > 0\n\t\t\t\t\t\t? filter\n\t\t\t\t\t\t: dim(\"type to filter or add pattern, ↑↓ navigate, space select\");\n\n\t\t\t\tswitch (this.state) {\n\t\t\t\t\tcase \"submit\": {\n\t\t\t\t\t\tconst summary =\n\t\t\t\t\t\t\tselected.size > 0\n\t\t\t\t\t\t\t\t? bld(Array.from(selected).join(\", \"))\n\t\t\t\t\t\t\t\t: dim(\"none\");\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)} ${summary}`;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"cancel\":\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)}`;\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${ylw(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\t\tfilter,\n\t\t\t\t\t\t\t\tcustomPatterns,\n\t\t\t\t\t\t\t\taddCursor,\n\t\t\t\t\t\t\t\toptional,\n\t\t\t\t\t\t\t\texcludedSet,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${ylw(S_BAR_END)} ${ylw(this.error)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${info(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tselected,\n\t\t\t\t\t\t\t\tfilter,\n\t\t\t\t\t\t\t\tcustomPatterns,\n\t\t\t\t\t\t\t\taddCursor,\n\t\t\t\t\t\t\t\toptional,\n\t\t\t\t\t\t\t\texcludedSet,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${info(S_BAR_END)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tfalse,\n\t) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n\tprompt.on(\"key\", (key: string | undefined) => {\n\t\tif (!key || key === \" \") return;\n\t\tconst cp = key.codePointAt(0) ?? 0;\n\t\tif (cp === 0x7f || cp === 0x08) {\n\t\t\tfilter = filter.slice(0, -1);\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t\taddCursor = false;\n\t\t} else if (cp >= 32 && cp !== 127) {\n\t\t\tfilter += key;\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t\taddCursor = false;\n\t\t}\n\t});\n\n\tprompt.on(\"cursor\", (action: string | undefined) => {\n\t\tconst filtered = getFiltered();\n\t\tconst hasAdd = isNewPattern();\n\n\t\tswitch (action) {\n\t\t\tcase \"up\":\n\t\t\t\tif (addCursor) {\n\t\t\t\t\taddCursor = false;\n\t\t\t\t\tcursor = Math.max(0, filtered.length - 1);\n\t\t\t\t} else cursor = Math.max(0, cursor - 1);\n\t\t\t\tbreak;\n\t\t\tcase \"down\":\n\t\t\t\tif (!addCursor && cursor >= filtered.length - 1 && hasAdd)\n\t\t\t\t\taddCursor = true;\n\t\t\t\telse if (!addCursor) cursor = Math.min(filtered.length - 1, cursor + 1);\n\t\t\t\tbreak;\n\t\t\tcase \"space\":\n\t\t\t\tif (addCursor) {\n\t\t\t\t\tconst t = filter.trim();\n\t\t\t\t\tconst err =\n\t\t\t\t\t\tvalidateBranchPattern(t) ??\n\t\t\t\t\t\t(excludedSet.has(t)\n\t\t\t\t\t\t\t? \"Already used for automatic translation\"\n\t\t\t\t\t\t\t: null);\n\t\t\t\t\tif (!err) {\n\t\t\t\t\t\tcustomPatterns.push(t);\n\t\t\t\t\t\tselected.add(t);\n\t\t\t\t\t\tfilter = \"\";\n\t\t\t\t\t\tcursor = 0;\n\t\t\t\t\t\tscrollOffset = 0;\n\t\t\t\t\t\taddCursor = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst item = filtered[cursor];\n\t\t\t\t\tif (item) {\n\t\t\t\t\t\tif (selected.has(item.value)) selected.delete(item.value);\n\t\t\t\t\t\telse selected.add(item.value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tprompt.on(\"finalize\", () => {\n\t\tif ((prompt as any).state === \"submit\") {\n\t\t\t(prompt as any).value = Array.from(selected);\n\t\t}\n\t});\n\n\tconst result = await prompt.prompt();\n\tif (isCancel(result)) return null;\n\treturn result as unknown as string[];\n}\n","import chalk from \"chalk\";\n\nconst ORANGE = \"#FC5206\";\nconst PINK = \"#D51977\";\nconst BLUE = \"#2450A9\";\n\nconst noColor = process.env.NO_COLOR === \"1\" || process.env.FORCE_COLOR === \"0\";\nconst hex = (color: string) => (s: string) =>\n\tnoColor ? s : chalk.hex(color)(s);\n\nexport const dim = (s: string) => (noColor ? s : chalk.dim(s));\nexport const bld = (s: string) => (noColor ? s : chalk.bold(s));\nexport const grn = (s: string) => (noColor ? s : chalk.green(s));\nexport const ylw = (s: string) => (noColor ? s : chalk.yellow(s));\nexport const red = (s: string) => (noColor ? s : chalk.red(s));\n\n/** Named values: file paths, locale codes, branch names, variable names */\nexport const highlight = hex(PINK);\n\n/** Structural info: bars, info logs, notes, links, selected checkmarks */\nexport const info = hex(BLUE);\n\n/** Brand identity: intro/outro text, active cursor ◆, spinner label accents */\nexport const active = hex(ORANGE);\n","import { isCancel, Prompt } from \"@clack/core\";\nimport * as p from \"@clack/prompts\";\nimport { active, bld, dim, grn, info, red, ylw } from \"./theme.js\";\n\nexport interface LocaleOption {\n\tbcp47: string;\n\t/** Human-readable label, e.g. \"English — en\" */\n\tlabel: string;\n}\n\n// ── Symbols (match @clack/prompts style) ──────────────────────────────────────\n\nconst S_BAR = \"│\";\nconst S_BAR_END = \"└\";\nconst S_ACTIVE = \"◆\";\nconst S_SUBMIT = \"◆\";\nconst S_CANCEL = \"■\";\nconst S_ERROR = \"▲\";\n\nfunction symbol(state: string): string {\n\tswitch (state) {\n\t\tcase \"submit\":\n\t\t\treturn grn(S_SUBMIT);\n\t\tcase \"cancel\":\n\t\t\treturn red(S_CANCEL);\n\t\tcase \"error\":\n\t\t\treturn ylw(S_ERROR);\n\t\tdefault:\n\t\t\treturn active(S_ACTIVE);\n\t}\n}\n\n// ── Filter ────────────────────────────────────────────────────────────────────\n\nconst MAX_VISIBLE = 12;\n\nfunction filterLocales(options: LocaleOption[], query: string): LocaleOption[] {\n\tif (!query.trim()) return options;\n\tconst lower = query.toLowerCase();\n\treturn options.filter(\n\t\t(o) =>\n\t\t\to.bcp47.toLowerCase().includes(lower) ||\n\t\t\to.label.toLowerCase().includes(lower),\n\t);\n}\n\n// ── List renderer ─────────────────────────────────────────────────────────────\n\nfunction buildList(\n\tfiltered: LocaleOption[],\n\tcursor: number,\n\tscrollOffset: number,\n\tselected: Set<string> | null, // null = single-select\n): string {\n\tconst isMulti = selected !== null;\n\tconst end = Math.min(filtered.length, scrollOffset + MAX_VISIBLE);\n\tconst visibleLines: string[] = [];\n\n\tfor (let i = scrollOffset; i < end; i++) {\n\t\tconst opt = filtered[i]!;\n\t\tconst isCursor = i === cursor;\n\t\tconst isChecked = isMulti && selected!.has(opt.bcp47);\n\n\t\tconst icon = isMulti\n\t\t\t? isChecked\n\t\t\t\t? isCursor\n\t\t\t\t\t? info(\"◼\")\n\t\t\t\t\t: info(\"◼\")\n\t\t\t\t: isCursor\n\t\t\t\t\t? active(\"◻\")\n\t\t\t\t\t: dim(\"◻\")\n\t\t\t: isCursor\n\t\t\t\t? active(\"●\")\n\t\t\t\t: dim(\"○\");\n\n\t\tvisibleLines.push(\n\t\t\t`${info(S_BAR)} ${icon} ${isCursor ? bld(opt.label) : opt.label}`,\n\t\t);\n\t}\n\n\tconst hidden = filtered.length - (end - scrollOffset);\n\tif (hidden > 0)\n\t\tvisibleLines.push(dim(`${S_BAR} ${hidden} more — keep typing to narrow`));\n\tif (filtered.length === 0) visibleLines.push(dim(`${S_BAR} No matches`));\n\tif (isMulti && selected!.size > 0) {\n\t\tvisibleLines.push(\n\t\t\tdim(`${S_BAR} ${selected!.size} selected — Enter to confirm`),\n\t\t);\n\t}\n\n\treturn visibleLines.join(\"\\n\");\n}\n\n// ── Core prompt factory ───────────────────────────────────────────────────────\n\nasync function runFilterablePrompt(opts: {\n\tmessage: string;\n\toptions: LocaleOption[];\n\tmulti: boolean;\n\tinitialValue?: string;\n\tinitialValues?: string[];\n}): Promise<string | string[] | null> {\n\tconst { message, options, multi } = opts;\n\n\tlet filter = \"\";\n\tlet cursor = 0;\n\tlet scrollOffset = 0;\n\tconst selected = new Set<string>(multi ? (opts.initialValues ?? []) : []);\n\n\tif (!multi && opts.initialValue) {\n\t\tconst idx = options.findIndex((o) => o.bcp47 === opts.initialValue);\n\t\tif (idx >= 0) cursor = idx;\n\t}\n\n\tconst getFiltered = () => filterLocales(options, filter);\n\n\t// Keep cursor in bounds and scroll window centred\n\tconst clampCursor = (filtered: LocaleOption[]) => {\n\t\tif (cursor >= filtered.length) cursor = Math.max(0, filtered.length - 1);\n\t\tif (cursor < scrollOffset) scrollOffset = cursor;\n\t\tif (cursor >= scrollOffset + MAX_VISIBLE)\n\t\t\tscrollOffset = cursor - MAX_VISIBLE + 1;\n\t\tif (scrollOffset < 0) scrollOffset = 0;\n\t};\n\n\t// @clack/core Prompt: render() returns the ENTIRE frame; clack handles\n\t// re-rendering (cursor movement + diff) automatically.\n\t// Using `any` cast to pass `trackValue=false` (2nd constructor arg).\n\tconst prompt = new (Prompt as any)(\n\t\t{\n\t\t\tinitialValue: !multi ? (options[cursor]?.bcp47 ?? null) : null,\n\t\t\tvalidate() {\n\t\t\t\tconst f = getFiltered();\n\t\t\t\tif (multi && selected.size === 0)\n\t\t\t\t\treturn \"At least one target language is required.\";\n\t\t\t\tif (!multi && !f[cursor]) return \"Please select a language.\";\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\trender(this: { state: string; error: string; value: unknown }) {\n\t\t\t\tconst filtered = getFiltered();\n\t\t\t\tclampCursor(filtered);\n\n\t\t\t\tconst hdr = `${dim(S_BAR)}\\n${symbol(this.state)} ${message}\\n`;\n\t\t\t\tconst hint =\n\t\t\t\t\tfilter.length > 0\n\t\t\t\t\t\t? filter\n\t\t\t\t\t\t: dim(\n\t\t\t\t\t\t\t\t`type to filter, ↑↓ navigate${multi ? \", space select\" : \"\"}`,\n\t\t\t\t\t\t\t);\n\n\t\t\t\tswitch (this.state) {\n\t\t\t\t\tcase \"submit\": {\n\t\t\t\t\t\tconst val = multi\n\t\t\t\t\t\t\t? Array.from(selected)\n\t\t\t\t\t\t\t\t\t.map((id) => options.find((o) => o.bcp47 === id)?.label ?? id)\n\t\t\t\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\t\t\t: (options.find((o) => o.bcp47 === (this.value as string))\n\t\t\t\t\t\t\t\t\t?.label ?? \"\");\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)} ${bld(val || dim(\"none\"))}`;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"cancel\":\n\t\t\t\t\t\treturn `${hdr}${dim(S_BAR)}`;\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${ylw(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tmulti ? selected : null,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${ylw(S_BAR_END)} ${ylw(this.error)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\thdr.trimEnd(),\n\t\t\t\t\t\t\t`${info(S_BAR)} ${dim(\"/\")} ${hint}`,\n\t\t\t\t\t\t\tbuildList(\n\t\t\t\t\t\t\t\tfiltered,\n\t\t\t\t\t\t\t\tcursor,\n\t\t\t\t\t\t\t\tscrollOffset,\n\t\t\t\t\t\t\t\tmulti ? selected : null,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t`${info(S_BAR_END)}`,\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t].join(\"\\n\");\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tfalse, // trackValue=false — we manage value manually\n\t) as InstanceType<typeof Prompt> & { value: unknown; state: string };\n\n\t// Character input → update filter\n\tprompt.on(\"key\", (key: string | undefined) => {\n\t\tif (!key || key === \" \") return; // space handled by cursor event\n\t\tconst cp = key.codePointAt(0) ?? 0;\n\t\tif (cp === 0x7f || cp === 0x08) {\n\t\t\t// backspace\n\t\t\tfilter = filter.slice(0, -1);\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t} else if (cp >= 32 && cp !== 127) {\n\t\t\tfilter += key;\n\t\t\tcursor = 0;\n\t\t\tscrollOffset = 0;\n\t\t}\n\t});\n\n\t// Navigation + toggle\n\tprompt.on(\"cursor\", (action: string | undefined) => {\n\t\tconst filtered = getFiltered();\n\t\tswitch (action) {\n\t\t\tcase \"up\":\n\t\t\t\tcursor = Math.max(0, cursor - 1);\n\t\t\t\tbreak;\n\t\t\tcase \"down\":\n\t\t\t\tcursor = Math.min(Math.max(filtered.length - 1, 0), cursor + 1);\n\t\t\t\tbreak;\n\t\t\tcase \"space\":\n\t\t\t\tif (multi) {\n\t\t\t\t\tconst opt = filtered[cursor];\n\t\t\t\t\tif (opt) {\n\t\t\t\t\t\tif (selected.has(opt.bcp47)) selected.delete(opt.bcp47);\n\t\t\t\t\t\telse selected.add(opt.bcp47);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\t// Sync prompt.value for single-select so submit gets the right value\n\t\tif (!multi) {\n\t\t\tconst opt = getFiltered()[cursor];\n\t\t\t(prompt as any).value = opt?.bcp47 ?? null;\n\t\t}\n\t});\n\n\t// Before submit resolves, set value to the selected items (multi) or current cursor (single)\n\tprompt.on(\"finalize\", () => {\n\t\tif ((prompt as any).state === \"submit\") {\n\t\t\tif (multi) {\n\t\t\t\t(prompt as any).value = Array.from(selected);\n\t\t\t} else {\n\t\t\t\tconst f = getFiltered();\n\t\t\t\t(prompt as any).value = f[cursor]?.bcp47 ?? null;\n\t\t\t}\n\t\t}\n\t});\n\n\tconst result = await prompt.prompt();\n\n\tif (isCancel(result)) return null;\n\treturn result as string | string[];\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport async function searchSelectLocale(\n\toptions: LocaleOption[],\n\tmessage: string,\n\tinitialValue?: string,\n): Promise<string | null> {\n\tconst result = await runFilterablePrompt({\n\t\tmessage,\n\t\toptions,\n\t\tmulti: false,\n\t\tinitialValue,\n\t});\n\treturn typeof result === \"string\" ? result : null;\n}\n\nexport async function searchMultiSelectLocales(\n\toptions: LocaleOption[],\n\tmessage: string,\n\tinitialValues?: string[],\n): Promise<string[] | null> {\n\tconst result = await runFilterablePrompt({\n\t\tmessage,\n\t\toptions,\n\t\tmulti: true,\n\t\tinitialValues,\n\t});\n\tif (result === null) return null;\n\tconst picks = result as string[];\n\t// Validate already prevents empty on first try; this handles the retry path\n\tif (picks.length === 0) {\n\t\tp.log.warn(\n\t\t\t\"At least one target language is required. Please select at least one.\",\n\t\t);\n\t\treturn searchMultiSelectLocales(options, message, initialValues);\n\t}\n\treturn picks;\n}\n","import { execSync } from \"node:child_process\";\nimport { relative, resolve } from \"node:path\";\n\nexport type GitRepositoryIdentity = {\n\trepoCanonical: string;\n\trepoAppDir: string;\n};\n\nexport type GitContext = {\n\tidentity: GitRepositoryIdentity | null;\n\twarnings: string[];\n};\n\nconst SHA_REGEX = /^[0-9a-f]{40}$/i;\n\n/**\n * Detect the current commit SHA from CI env vars or git.\n * Must produce the same result as detectCommitSha() in @vocoder/plugin\n * so fingerprints computed by CLI sync and unplugin build match.\n */\nexport function detectCommitSha(): string | null {\n\tif (\n\t\tprocess.env.VOCODER_COMMIT_SHA &&\n\t\tSHA_REGEX.test(process.env.VOCODER_COMMIT_SHA)\n\t) {\n\t\treturn process.env.VOCODER_COMMIT_SHA;\n\t}\n\n\tconst knownSha =\n\t\tprocess.env.GITHUB_SHA ||\n\t\tprocess.env.VERCEL_GIT_COMMIT_SHA ||\n\t\tprocess.env.CI_COMMIT_SHA ||\n\t\tprocess.env.BITBUCKET_COMMIT ||\n\t\tprocess.env.CIRCLE_SHA1 ||\n\t\tprocess.env.RENDER_GIT_COMMIT;\n\n\tif (knownSha && SHA_REGEX.test(knownSha)) return knownSha;\n\n\treturn safeExec(\"git rev-parse HEAD\");\n}\n\nfunction safeExec(command: string): string | null {\n\ttry {\n\t\tconst output = execSync(command, {\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t}).trim();\n\t\treturn output.length > 0 ? output : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction normalizePath(pathname: string): string | null {\n\tconst cleaned = pathname\n\t\t.replace(/^\\/+/, \"\")\n\t\t.replace(/\\.git$/i, \"\")\n\t\t.trim();\n\n\tif (!cleaned || !cleaned.includes(\"/\")) {\n\t\treturn null;\n\t}\n\n\treturn cleaned;\n}\n\nfunction parseRemoteUrl(remoteUrl: string): {\n\thost: string;\n\townerRepoPath: string;\n} | null {\n\tconst trimmed = remoteUrl.trim();\n\tif (!trimmed) {\n\t\treturn null;\n\t}\n\n\t// SCP-like syntax: git@github.com:owner/repo.git\n\tif (!trimmed.includes(\"://\")) {\n\t\tconst scpMatch = trimmed.match(/^(?:.+@)?([^:]+):(.+)$/);\n\t\tif (scpMatch) {\n\t\t\tconst host = (scpMatch[1] || \"\").toLowerCase();\n\t\t\tconst ownerRepoPath = normalizePath(scpMatch[2] || \"\");\n\t\t\tif (!host || !ownerRepoPath) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn { host, ownerRepoPath };\n\t\t}\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst parsed = new URL(trimmed);\n\t\tconst host = parsed.hostname.toLowerCase();\n\t\tconst ownerRepoPath = normalizePath(decodeURIComponent(parsed.pathname));\n\t\tif (!host || !ownerRepoPath) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { host, ownerRepoPath };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction toCanonical(host: string, ownerRepoPath: string): string {\n\tif (host.includes(\"github.com\")) {\n\t\treturn `github:${ownerRepoPath.toLowerCase()}`;\n\t}\n\tif (host.includes(\"gitlab.com\")) {\n\t\treturn `gitlab:${ownerRepoPath.toLowerCase()}`;\n\t}\n\tif (host.includes(\"bitbucket.org\")) {\n\t\treturn `bitbucket:${ownerRepoPath.toLowerCase()}`;\n\t}\n\treturn `git:${host}/${ownerRepoPath.toLowerCase()}`;\n}\n\nexport function resolveGitRepositoryIdentity(): GitRepositoryIdentity | null {\n\tconst remoteUrl = safeExec(\"git config --get remote.origin.url\");\n\tif (!remoteUrl) {\n\t\treturn null;\n\t}\n\n\tconst parsed = parseRemoteUrl(remoteUrl);\n\tif (!parsed) {\n\t\treturn null;\n\t}\n\n\tconst repositoryRoot = safeExec(\"git rev-parse --show-toplevel\");\n\tconst currentDirectory = process.cwd();\n\tlet repoAppDir = \"\";\n\tif (repositoryRoot) {\n\t\tconst relativePath = relative(\n\t\t\tresolve(repositoryRoot),\n\t\t\tresolve(currentDirectory),\n\t\t)\n\t\t\t.replace(/\\\\/g, \"/\")\n\t\t\t.trim();\n\n\t\tif (\n\t\t\trelativePath &&\n\t\t\trelativePath !== \".\" &&\n\t\t\t!relativePath.startsWith(\"..\")\n\t\t) {\n\t\t\trepoAppDir = relativePath;\n\t\t}\n\t}\n\n\treturn {\n\t\trepoCanonical: toCanonical(parsed.host, parsed.ownerRepoPath),\n\t\trepoAppDir,\n\t};\n}\n\nexport function resolveGitContext(): GitContext {\n\tconst warnings: string[] = [];\n\tconst identity = resolveGitRepositoryIdentity();\n\n\tif (!identity) {\n\t\twarnings.push(\n\t\t\t\"Could not detect git remote origin. Repo binding will be skipped until sync can detect it.\",\n\t\t);\n\t}\n\n\treturn { identity, warnings };\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\n\nexport interface WorkspaceInfo {\n\tid: string;\n\tname: string;\n\tplanId: string;\n\tprojectCount: number;\n\thasGitHubConnection: boolean;\n\tconnectionLabel: string | null;\n}\n\nexport interface WorkspaceListResult {\n\tworkspaces: WorkspaceInfo[];\n\tcanCreateWorkspace: boolean;\n}\n\nexport type WorkspaceSelection =\n\t| { action: \"use\"; workspace: WorkspaceInfo }\n\t| { action: \"create\" }\n\t| { action: \"cancelled\" };\n\nfunction _workspaceLabel(ws: WorkspaceInfo): string {\n\tconst parts: string[] = [ws.name];\n\tconst meta: string[] = [];\n\n\tif (ws.projectCount === 1) {\n\t\tmeta.push(\"1 project\");\n\t} else if (ws.projectCount > 1) {\n\t\tmeta.push(`${ws.projectCount} projects`);\n\t}\n\n\tif (ws.connectionLabel) {\n\t\tmeta.push(`GitHub: ${ws.connectionLabel}`);\n\t}\n\n\tif (meta.length > 0) {\n\t\tparts.push(chalk.dim(`(${meta.join(\", \")})`));\n\t}\n\n\treturn parts.join(\" \");\n}\n\n/**\n * Prompt the user to select a workspace or create a new one.\n * Returns a `WorkspaceSelection` describing what the user chose.\n */\nexport async function selectWorkspace(\n\tresult: WorkspaceListResult,\n): Promise<WorkspaceSelection> {\n\tconst { workspaces, canCreateWorkspace } = result;\n\n\tif (workspaces.length === 0) {\n\t\t// No workspaces — must create\n\t\treturn { action: \"create\" };\n\t}\n\n\ttype SelectValue = string | \"create\";\n\n\tconst options: Array<{ value: SelectValue; label: string; hint?: string }> =\n\t\tworkspaces.map((ws) => ({\n\t\t\tvalue: ws.id,\n\t\t\tlabel: ws.name,\n\t\t\thint:\n\t\t\t\t[\n\t\t\t\t\tws.projectCount > 0\n\t\t\t\t\t\t? `${ws.projectCount} project${ws.projectCount !== 1 ? \"s\" : \"\"}`\n\t\t\t\t\t\t: \"\",\n\t\t\t\t\tws.connectionLabel ? `GitHub: ${ws.connectionLabel}` : \"\",\n\t\t\t\t]\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join(\" · \") || undefined,\n\t\t}));\n\n\tif (canCreateWorkspace) {\n\t\toptions.push({ value: \"create\", label: \"Create new workspace\" });\n\t}\n\n\tconst selected = await p.select<SelectValue>({\n\t\tmessage: \"Select workspace\",\n\t\toptions,\n\t});\n\n\tif (p.isCancel(selected)) {\n\t\treturn { action: \"cancelled\" };\n\t}\n\n\tif (selected === \"create\") {\n\t\treturn { action: \"create\" };\n\t}\n\n\tconst workspace = workspaces.find((ws) => ws.id === selected);\n\tif (!workspace) {\n\t\treturn { action: \"cancelled\" };\n\t}\n\n\treturn { action: \"use\", workspace };\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport { getLimitErrorGuidance } from \"./sync.js\";\n\nloadEnv();\n\nexport interface LocaleCommandOptions {\n\tapiUrl?: string;\n}\n\nfunction getApiConfig(options: LocaleCommandOptions): {\n\tapiKey: string;\n\tapiUrl: string;\n} | null {\n\tconst apiKey = process.env.VOCODER_API_KEY;\n\tif (!apiKey) {\n\t\tp.log.error(\n\t\t\t\"VOCODER_API_KEY is not set. Run `npx @vocoder/cli init` to set up your project.\",\n\t\t);\n\t\treturn null;\n\t}\n\treturn {\n\t\tapiKey,\n\t\tapiUrl: options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\",\n\t};\n}\n\n/**\n * Lists the project's configured source locale and target locales.\n * Reads the project API key from VOCODER_API_KEY.\n *\n * Endpoint: GET /api/cli/config\n *\n * @throws If VOCODER_API_KEY is missing or the API call fails.\n */\nexport async function listProjectLocales(options: LocaleCommandOptions = {}): Promise<number> {\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\n\ttry {\n\t\tconst projectConfig = await api.getAppConfig();\n\n\t\tp.log.info(\n\t\t\t`Source locale: ${highlight(projectConfig.sourceLocale)}`,\n\t\t);\n\n\t\tif (projectConfig.targetLocales.length === 0) {\n\t\t\tp.log.info(\"Target locales: (none configured)\");\n\t\t} else {\n\t\t\tp.log.info(\n\t\t\t\t`Target locales: ${projectConfig.targetLocales.map((l) => highlight(l)).join(\", \")}`,\n\t\t\t);\n\t\t}\n\n\t\treturn 0;\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to fetch project locales.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n\n/**\n * Adds one or more target locales to the project.\n * Loops per locale — the API accepts one locale at a time.\n * Idempotent: locales already configured are silently skipped.\n *\n * Endpoint: POST /api/cli/project/locales (one call per locale)\n *\n * @param locales Array of BCP 47 locale codes to add, e.g. [\"fr\", \"de\", \"pt-BR\"].\n * @throws {VocoderAPIError} status 422 for invalid/unsupported locale code.\n * @throws {VocoderAPIError} status 403 when the plan's maxTargetLocalesPerProject limit is reached.\n */\nexport async function addLocales(\n\tlocales: string[],\n\toptions: LocaleCommandOptions = {},\n): Promise<number> {\n\tif (locales.length === 0) {\n\t\tp.log.error(\"No locale codes provided.\");\n\t\treturn 1;\n\t}\n\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\tlet lastTargetLocales: string[] = [];\n\tlet hadError = false;\n\n\tfor (const locale of locales) {\n\t\tconst spinner = p.spinner();\n\t\tspinner.start(`Adding ${locale}…`);\n\n\t\ttry {\n\t\t\tconst result = await api.addLocale(locale);\n\t\t\tlastTargetLocales = result.targetLocales;\n\t\t\tspinner.stop(`Added ${highlight(locale)}`);\n\t\t} catch (error) {\n\t\t\tspinner.stop(`Failed to add ${chalk.red(locale)}`);\n\t\t\thadError = true;\n\n\t\t\tif (error instanceof VocoderAPIError && error.limitError) {\n\t\t\t\tconst { limitError } = error;\n\t\t\t\tp.log.error(limitError.message);\n\t\t\t\tfor (const line of getLimitErrorGuidance(limitError)) {\n\t\t\t\t\tp.log.info(line);\n\t\t\t\t}\n\t\t\t\t// Plan limit hit — remaining locales will also fail, so stop early\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tp.log.error(\n\t\t\t\terror instanceof Error ? error.message : \"Unknown error\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastTargetLocales.length > 0) {\n\t\tp.log.info(\n\t\t\t`Target locales now: ${lastTargetLocales.map((l) => highlight(l)).join(\", \")}`,\n\t\t);\n\t}\n\n\treturn hadError ? 1 : 0;\n}\n\n/**\n * Removes one or more target locales from the project.\n * Loops per locale — the API accepts one locale at a time.\n * Idempotent: locales not currently configured are silently skipped.\n *\n * Endpoint: DELETE /api/cli/project/locales (one call per locale)\n *\n * @param locales Array of BCP 47 locale codes to remove, e.g. [\"fr\", \"de\"].\n */\nexport async function removeLocales(\n\tlocales: string[],\n\toptions: LocaleCommandOptions = {},\n): Promise<number> {\n\tif (locales.length === 0) {\n\t\tp.log.error(\"No locale codes provided.\");\n\t\treturn 1;\n\t}\n\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\tlet lastTargetLocales: string[] = [];\n\tlet hadError = false;\n\n\tfor (const locale of locales) {\n\t\tconst spinner = p.spinner();\n\t\tspinner.start(`Removing ${locale}…`);\n\n\t\ttry {\n\t\t\tconst result = await api.removeLocale(locale);\n\t\t\tlastTargetLocales = result.targetLocales;\n\t\t\tspinner.stop(`Removed ${highlight(locale)}`);\n\t\t} catch (error) {\n\t\t\tspinner.stop(`Failed to remove ${chalk.red(locale)}`);\n\t\t\thadError = true;\n\t\t\tp.log.error(\n\t\t\t\terror instanceof Error ? error.message : \"Unknown error\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (lastTargetLocales.length > 0) {\n\t\tp.log.info(\n\t\t\t`Target locales now: ${lastTargetLocales.map((l) => highlight(l)).join(\", \")}`,\n\t\t);\n\t} else if (!hadError) {\n\t\tp.log.info(\"Target locales now: (none configured)\");\n\t}\n\n\treturn hadError ? 1 : 0;\n}\n\n/**\n * Lists all locales supported by Vocoder.\n * Useful for discovering valid BCP 47 codes before calling `add`.\n *\n * Endpoint: GET /api/cli/locales (accepts both user tokens and project API keys)\n */\nexport async function listSupportedLocales(options: LocaleCommandOptions = {}): Promise<number> {\n\tconst config = getApiConfig(options);\n\tif (!config) return 1;\n\n\tconst api = new VocoderAPI(config);\n\n\ttry {\n\t\t// GET /api/cli/locales accepts both user tokens and project API keys as Bearer tokens\n\t\tconst result = await api.listLocales(config.apiKey);\n\t\tp.log.info(chalk.bold(\"Source locales:\"));\n\t\tprintLocaleTable(result.sourceLocales);\n\t\tp.log.info(\"\");\n\t\tp.log.info(chalk.bold(\"Target locales:\"));\n\t\tprintLocaleTable(result.targetLocales);\n\t\treturn 0;\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to fetch supported locales.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n\nfunction printLocaleTable(\n\tlocales: Array<{ code: string; name: string; nativeName?: string }>,\n): void {\n\tfor (const locale of locales) {\n\t\tconst native =\n\t\t\tlocale.nativeName && locale.nativeName !== locale.name\n\t\t\t\t? ` (${locale.nativeName})`\n\t\t\t\t: \"\";\n\t\tp.log.info(` ${highlight(locale.code.padEnd(10))} ${locale.name}${native}`);\n\t}\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { highlight } from \"../utils/theme.js\";\nimport type { VocoderTranslationData } from \"@vocoder/config\";\nimport { loadVocoderConfig } from \"@vocoder/extractor\";\nimport type {\n\tEffectiveSyncMode,\n\tExtractedString,\n\tLimitErrorResponse,\n\tLocalesMap,\n\tProjectConfig,\n\tRequestedSyncMode,\n\tSyncPolicyConfig,\n\tTranslateOptions,\n\tTranslationStringEntry,\n} from \"../types.js\";\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport { detectBranch, isTargetBranch } from \"../utils/branch.js\";\nimport { getMergedConfig, validateLocalConfig } from \"../utils/config.js\";\nimport { StringExtractor } from \"../utils/extract.js\";\nimport {\n\tdetectCommitSha,\n\tresolveGitRepositoryIdentity,\n} from \"../utils/git-identity.js\";\n\ntype LocaleMetadataMap = LocalesMap;\ntype TranslationMap = Record<string, Record<string, string>>;\ntype TranslationArtifactSource = \"fresh\" | \"local-cache\" | \"api-snapshot\";\n\ntype TranslationArtifacts = {\n\tsource: TranslationArtifactSource;\n\ttranslations: TranslationMap;\n\tlocaleMetadata?: LocaleMetadataMap;\n\tsnapshotBatchId?: string;\n\tcompletedAt?: string | null;\n};\n\nfunction computeFingerprint(shortCode: string, texts: string[]): string {\n\tconst sorted = [...texts].sort();\n\treturn createHash(\"sha256\")\n\t\t.update(`${shortCode}:${sorted.join(\"\\0\")}`)\n\t\t.digest(\"hex\")\n\t\t.slice(0, 12);\n}\n\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseLocaleMetadata(value: unknown): LocaleMetadataMap | undefined {\n\tif (!isRecord(value)) {\n\t\treturn undefined;\n\t}\n\n\tconst metadata: LocaleMetadataMap = {};\n\tfor (const [locale, rawValue] of Object.entries(value)) {\n\t\tif (!isRecord(rawValue)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nativeName = rawValue.nativeName;\n\t\tif (typeof nativeName !== \"string\" || nativeName.trim().length === 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entry: { nativeName: string; dir?: \"rtl\" } = { nativeName };\n\t\tif (rawValue.dir === \"rtl\") {\n\t\t\tentry.dir = \"rtl\";\n\t\t}\n\n\t\tmetadata[locale] = entry;\n\t}\n\n\treturn Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction parseTranslations(value: unknown): TranslationMap | null {\n\tif (!isRecord(value)) {\n\t\treturn null;\n\t}\n\n\tconst translations: TranslationMap = {};\n\n\tfor (const [locale, localeValue] of Object.entries(value)) {\n\t\tif (!isRecord(localeValue)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst localeTranslations: Record<string, string> = {};\n\t\tfor (const [source, translated] of Object.entries(localeValue)) {\n\t\t\tif (typeof translated === \"string\") {\n\t\t\t\tlocaleTranslations[source] = translated;\n\t\t\t}\n\t\t}\n\n\t\ttranslations[locale] = localeTranslations;\n\t}\n\n\treturn Object.keys(translations).length > 0 ? translations : null;\n}\n\nfunction getCacheFilePath(projectRoot: string, fingerprint: string): string {\n\treturn join(projectRoot, \"node_modules\", \".vocoder\", \"cache\", `${fingerprint}.json`);\n}\n\nfunction buildTranslationData(params: {\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\tstringEntries: TranslationStringEntry[];\n\ttranslations: TranslationMap;\n\tlocaleMetadata?: LocaleMetadataMap;\n\tupdatedAt: string;\n}): VocoderTranslationData {\n\t// Remap text-keyed translations → hash-keyed using the string entries the CLI already has\n\tconst textToHash = new Map(params.stringEntries.map((e) => [e.text, e.key]));\n\tconst hashKeyed: TranslationMap = {};\n\tfor (const [locale, localeMap] of Object.entries(params.translations)) {\n\t\thashKeyed[locale] = {};\n\t\tfor (const [text, translation] of Object.entries(localeMap)) {\n\t\t\tconst hash = textToHash.get(text);\n\t\t\tif (hash) hashKeyed[locale][hash] = translation;\n\t\t}\n\t}\n\n\tconst locales: Record<string, { nativeName: string; dir?: \"rtl\" }> = {};\n\tfor (const code of [params.sourceLocale, ...params.targetLocales]) {\n\t\tconst meta = params.localeMetadata?.[code];\n\t\tif (meta) locales[code] = { nativeName: meta.nativeName, ...(meta.dir ? { dir: meta.dir } : {}) };\n\t}\n\n\treturn {\n\t\tconfig: { sourceLocale: params.sourceLocale, targetLocales: params.targetLocales, locales },\n\t\ttranslations: hashKeyed,\n\t\tupdatedAt: params.updatedAt,\n\t};\n}\n\nfunction readLocalCache(params: {\n\tprojectRoot: string;\n\tfingerprint: string;\n}): TranslationArtifacts | null {\n\tconst cacheFilePath = getCacheFilePath(params.projectRoot, params.fingerprint);\n\tif (!existsSync(cacheFilePath)) return null;\n\ttry {\n\t\tconst raw = readFileSync(cacheFilePath, \"utf-8\");\n\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\tif (!isRecord(parsed)) return null;\n\t\t// VocoderTranslationData shape: { config, translations, updatedAt }\n\t\tconst inner = isRecord(parsed.config) ? parsed : null;\n\t\tif (!inner) return null;\n\t\tconst translations = parseTranslations(inner.translations);\n\t\tif (!translations) return null;\n\t\tconst localeMetadata = isRecord(inner.config)\n\t\t\t? parseLocaleMetadata(inner.config.locales)\n\t\t\t: undefined;\n\t\treturn { source: \"local-cache\", translations, localeMetadata };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction writeCache(params: {\n\tprojectRoot: string;\n\tfingerprint: string;\n\tdata: VocoderTranslationData;\n}): string {\n\tconst cacheDir = join(params.projectRoot, \"node_modules\", \".vocoder\", \"cache\");\n\tmkdirSync(cacheDir, { recursive: true });\n\tconst cacheFilePath = getCacheFilePath(params.projectRoot, params.fingerprint);\n\twriteFileSync(cacheFilePath, JSON.stringify(params.data), \"utf-8\");\n\treturn cacheFilePath;\n}\n\nfunction resolveEffectiveModeFromPolicy(params: {\n\tbranch: string;\n\trequestedMode: RequestedSyncMode;\n\tpolicy: SyncPolicyConfig;\n}): EffectiveSyncMode {\n\tconst { requestedMode, policy, branch } = params;\n\n\tlet mode: EffectiveSyncMode;\n\tif (requestedMode === \"auto\") {\n\t\tconst isBlockingBranch = isTargetBranch(branch, policy.blockingBranches);\n\t\tmode = isBlockingBranch ? policy.blockingMode : policy.nonBlockingMode;\n\t} else {\n\t\tmode = requestedMode;\n\t}\n\n\treturn mode;\n}\n\nfunction resolveWaitTimeoutMs(params: {\n\trequestedMaxWaitMs?: number;\n\tpolicyDefaultMaxWaitMs?: number;\n\tfallbackTimeoutMs: number;\n}): number {\n\tif (\n\t\ttypeof params.requestedMaxWaitMs === \"number\" &&\n\t\tNumber.isFinite(params.requestedMaxWaitMs) &&\n\t\tparams.requestedMaxWaitMs > 0\n\t) {\n\t\treturn Math.floor(params.requestedMaxWaitMs);\n\t}\n\n\tif (\n\t\ttypeof params.policyDefaultMaxWaitMs === \"number\" &&\n\t\tNumber.isFinite(params.policyDefaultMaxWaitMs) &&\n\t\tparams.policyDefaultMaxWaitMs > 0\n\t) {\n\t\treturn Math.floor(params.policyDefaultMaxWaitMs);\n\t}\n\n\treturn params.fallbackTimeoutMs;\n}\n\nfunction normalizeTranslations(params: {\n\tsourceLocale: string;\n\ttargetLocales: string[];\n\tsourceStrings: string[];\n\ttranslations: TranslationMap;\n}): TranslationMap {\n\tconst merged: TranslationMap = {};\n\n\tfor (const [locale, values] of Object.entries(params.translations)) {\n\t\tmerged[locale] = { ...values };\n\t}\n\n\tconst expectedLocales = [\n\t\tparams.sourceLocale,\n\t\t...params.targetLocales.filter((locale) => locale !== params.sourceLocale),\n\t];\n\n\tfor (const locale of expectedLocales) {\n\t\tif (!merged[locale]) {\n\t\t\tmerged[locale] = {};\n\t\t}\n\t}\n\n\tif (!merged[params.sourceLocale]) {\n\t\tmerged[params.sourceLocale] = {};\n\t}\n\n\tfor (const sourceText of params.sourceStrings) {\n\t\tif (!(sourceText in merged[params.sourceLocale]!)) {\n\t\t\tmerged[params.sourceLocale]![sourceText] = sourceText;\n\t\t}\n\t}\n\n\treturn merged;\n}\n\nexport function getLimitErrorGuidance(\n\tlimitError: LimitErrorResponse,\n): string[] {\n\tif (limitError.limitType === \"providers\") {\n\t\treturn [\n\t\t\t\"Provider setup required.\",\n\t\t\t\"Add a DeepL API key in Dashboard -> Workspace Settings -> Providers.\",\n\t\t\t`Open settings: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\tif (limitError.limitType === \"translation_chars\") {\n\t\treturn [\n\t\t\t\"Monthly translation character limit reached.\",\n\t\t\t`Used this month: ${limitError.current.toLocaleString()} chars`,\n\t\t\t`Requested after sync: ${limitError.required.toLocaleString()} chars`,\n\t\t\t`Upgrade plan: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\tif (limitError.limitType === \"source_strings\") {\n\t\treturn [\n\t\t\t\"Active source string limit reached.\",\n\t\t\t`Current active strings: ${limitError.current.toLocaleString()}`,\n\t\t\t`Required for this sync: ${limitError.required.toLocaleString()}`,\n\t\t\t`Upgrade plan: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\tif (limitError.limitType === \"target_locales\") {\n\t\treturn [\n\t\t\t`Current target locales: ${limitError.current}`,\n\t\t\t`Plan limit: ${limitError.current} (${limitError.planId})`,\n\t\t\t`Upgrade plan: ${limitError.upgradeUrl}`,\n\t\t];\n\t}\n\n\treturn [\n\t\t`Plan: ${limitError.planId}`,\n\t\t`Current: ${limitError.current}`,\n\t\t`Required: ${limitError.required}`,\n\t\t`Upgrade: ${limitError.upgradeUrl}`,\n\t];\n}\n\nfunction getSyncPolicyErrorGuidance(\n\terror: NonNullable<VocoderAPIError[\"syncPolicyError\"]>,\n): string[] {\n\tif (error.errorCode === \"BRANCH_NOT_ALLOWED\") {\n\t\tconst lines = [\"This branch is not allowed for this project.\"];\n\t\tif (error.branch) {\n\t\t\tlines.push(`Current branch: ${error.branch}`);\n\t\t}\n\t\t// targetBranches removed — configure branches in project settings\n\t\tlines.push(\n\t\t\t\"Update your project target branches in the dashboard if needed.\",\n\t\t);\n\t\treturn lines;\n\t}\n\n\tconst lines = [\"This project is bound to a different repository.\"];\n\tif (error.boundRepoLabel) {\n\t\tlines.push(`Bound repository: ${error.boundRepoLabel}`);\n\t}\n\tif (error.boundScopePath) {\n\t\tlines.push(`Bound scope: ${error.boundScopePath}`);\n\t}\n\tlines.push(\n\t\t\"Run `vocoder init` from the correct repository or create a separate project.\",\n\t);\n\treturn lines;\n}\n\nfunction mergeContext(\n\tcurrent: string | undefined,\n\tincoming: string | undefined,\n): string | undefined {\n\tif (!incoming) return current;\n\tif (!current) return incoming;\n\tif (current === incoming) return current;\n\n\tconst merged = new Set(\n\t\t[...current.split(\" | \"), ...incoming.split(\" | \")]\n\t\t\t.map((part) => part.trim())\n\t\t\t.filter(Boolean),\n\t);\n\treturn Array.from(merged).join(\" | \");\n}\n\nfunction buildStringEntries(\n\textractedStrings: ExtractedString[],\n): TranslationStringEntry[] {\n\tconst byText = new Map<string, TranslationStringEntry>();\n\n\tfor (const str of extractedStrings) {\n\t\tconst existing = byText.get(str.text);\n\t\tif (!existing) {\n\t\t\tbyText.set(str.text, {\n\t\t\t\tkey: str.key,\n\t\t\t\ttext: str.text,\n\t\t\t\t...(str.context ? { context: str.context } : {}),\n\t\t\t\t...(str.formality ? { formality: str.formality } : {}),\n\t\t\t\t...(str.uiRole ? { uiRole: str.uiRole } : {}),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\texisting.context = mergeContext(existing.context, str.context);\n\n\t\tif (!existing.formality && str.formality) {\n\t\t\texisting.formality = str.formality;\n\t\t} else if (\n\t\t\texisting.formality &&\n\t\t\tstr.formality &&\n\t\t\texisting.formality !== str.formality\n\t\t) {\n\t\t\texisting.formality = \"auto\";\n\t\t}\n\n\t\tif (str.key < existing.key) {\n\t\t\texisting.key = str.key;\n\t\t}\n\t}\n\n\treturn Array.from(byText.values());\n}\n\nasync function fetchApiSnapshot(\n\tapi: VocoderAPI,\n\tparams: {\n\t\tbranch: string;\n\t\ttargetLocales: string[];\n\t},\n): Promise<TranslationArtifacts | null> {\n\tconst snapshot = await api.getTranslationSnapshot({\n\t\tbranch: params.branch,\n\t\ttargetLocales: params.targetLocales,\n\t});\n\n\tif (snapshot.status !== \"FOUND\" || !snapshot.translations) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tsource: \"api-snapshot\",\n\t\ttranslations: snapshot.translations,\n\t\tlocaleMetadata: snapshot.localeMetadata,\n\t\tsnapshotBatchId: snapshot.snapshotBatchId,\n\t\tcompletedAt: snapshot.completedAt,\n\t};\n}\n\n/**\n * Main sync command\n */\nexport async function sync(options: TranslateOptions = {}): Promise<number> {\n\tconst startTime = Date.now();\n\tconst projectRoot = process.cwd();\n\n\tp.intro(\"Vocoder Sync\");\n\n\t// Check for API key before doing any work — missing key is an onboarding\n\t// issue, not an error. Show friendly guidance and exit cleanly.\n\tconst mergedConfig = await getMergedConfig(options, options.verbose);\n\tif (!mergedConfig.apiKey) {\n\t\tp.log.warn(\"No API key found. Run init to get started:\");\n\t\tp.log.info(\" npx @vocoder/cli init\");\n\t\tp.log.info(\"\");\n\t\tp.log.info(\n\t\t\t\" Or add your key to .env: VOCODER_API_KEY=vca_...\",\n\t\t);\n\t\tp.outro(\"Run `npx @vocoder/cli init` to set up your project.\");\n\t\treturn 1;\n\t}\n\n\tconst spinner = p.spinner();\n\n\ttry {\n\t\tconst branch = detectBranch(options.branch);\n\n\t\tspinner.start(\"Loading project configuration\");\n\n\t\tconst localConfig = {\n\t\t\tapiKey: mergedConfig.apiKey,\n\t\t\tapiUrl: mergedConfig.apiUrl || \"https://vocoder.app\",\n\t\t};\n\t\tvalidateLocalConfig(localConfig);\n\n\t\tconst api = new VocoderAPI(localConfig);\n\t\tconst apiConfig = await api.getAppConfig();\n\n\t\tconst requestedMode = mergedConfig.mode;\n\t\tconst waitTimeoutMs = resolveWaitTimeoutMs({\n\t\t\trequestedMaxWaitMs: mergedConfig.maxWaitMs,\n\t\t\tpolicyDefaultMaxWaitMs: apiConfig.syncPolicy.defaultMaxWaitMs,\n\t\t\tfallbackTimeoutMs: 60_000,\n\t\t});\n\n\t\tconst fileConfig = loadVocoderConfig(process.cwd());\n\t\tconst config: ProjectConfig = {\n\t\t\t...localConfig,\n\t\t\t...apiConfig,\n\t\t\tincludePattern: mergedConfig.includePattern,\n\t\t\texcludePattern: mergedConfig.excludePattern,\n\t\t\ttimeout: waitTimeoutMs,\n\t\t\t...(fileConfig?.appIndustry ? { appIndustry: fileConfig.appIndustry } : {}),\n\t\t\t...(fileConfig?.formality ? { formality: fileConfig.formality } : {}),\n\t\t};\n\n\t\tspinner.stop(`Branch: ${highlight(branch)}`);\n\n\t\tif (!options.force && !isTargetBranch(branch, config.targetBranches)) {\n\t\t\tp.log.warn(\n\t\t\t\t`Skipping translations (${highlight(branch)} is not a target branch)`,\n\t\t\t);\n\t\t\tp.log.info(`Target branches: ${config.targetBranches.join(\", \")}`);\n\t\t\tp.log.info(\"Use --force to translate anyway\");\n\t\t\tp.outro(\"\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst patternsDisplay = Array.isArray(config.includePattern)\n\t\t\t? config.includePattern.join(\", \")\n\t\t\t: config.includePattern;\n\n\t\tspinner.start(`Extracting strings from ${patternsDisplay}`);\n\t\tconst extractor = new StringExtractor();\n\t\tconst extractedStrings = await extractor.extractFromProject(\n\t\t\tconfig.includePattern,\n\t\t\tprojectRoot,\n\t\t\tconfig.excludePattern,\n\t\t);\n\n\t\tif (extractedStrings.length === 0) {\n\t\t\tspinner.stop(\"No translatable strings found\");\n\t\t\tp.log.warn(\n\t\t\t\t\"Make sure you are wrapping translatable strings with Vocoder\",\n\t\t\t);\n\t\t\tp.outro(\"\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tspinner.stop(\n\t\t\t`Extracted ${highlight(extractedStrings.length)} strings from ${highlight(patternsDisplay)}`,\n\t\t);\n\n\t\tif (options.verbose) {\n\t\t\tconst sampleLines = extractedStrings\n\t\t\t\t.slice(0, 5)\n\t\t\t\t.map((s: ExtractedString) => ` \"${s.text}\" (${s.file}:${s.line})`);\n\t\t\tif (extractedStrings.length > 5) {\n\t\t\t\tsampleLines.push(` ... and ${extractedStrings.length - 5} more`);\n\t\t\t}\n\t\t\tp.note(sampleLines.join(\"\\n\"), \"Sample strings\");\n\t\t}\n\n\t\tif (options.dryRun) {\n\t\t\tp.note(\n\t\t\t\t[\n\t\t\t\t\t`Strings: ${extractedStrings.length}`,\n\t\t\t\t\t`Branch: ${branch}`,\n\t\t\t\t\t`Target locales: ${config.targetLocales.join(\", \")}`,\n\t\t\t\t\t`Requested mode: ${requestedMode}`,\n\t\t\t\t\t`Max wait: ${waitTimeoutMs}ms`,\n\t\t\t\t\t`No fallback: ${mergedConfig.noFallback ? \"yes\" : \"no\"}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\t\"Dry run - would translate\",\n\t\t\t);\n\t\t\tp.outro(\"No API calls made.\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tconst repoIdentity = resolveGitRepositoryIdentity();\n\t\tif (!repoIdentity && options.verbose) {\n\t\t\tp.log.warn(\n\t\t\t\t\"Could not detect git remote origin. Sync will continue without repo metadata.\",\n\t\t\t);\n\t\t}\n\t\tconst commitSha = detectCommitSha() ?? undefined;\n\n\t\tconst stringEntries = buildStringEntries(extractedStrings);\n\t\tconst sourceStrings = stringEntries.map((entry) => entry.text);\n\n\t\tif (options.verbose && stringEntries.length !== extractedStrings.length) {\n\t\t\tp.log.info(\n\t\t\t\t`Deduped ${extractedStrings.length} extracted entries into ${stringEntries.length} unique source strings`,\n\t\t\t);\n\t\t}\n\n\t\tconst fingerprint = computeFingerprint(config.shortCode, sourceStrings);\n\n\t\t// Local cache check — skip API submission if translations already exist for this fingerprint.\n\t\tif (!options.force) {\n\t\t\tconst cacheFile = getCacheFilePath(projectRoot, fingerprint);\n\t\t\tif (existsSync(cacheFile)) {\n\t\t\t\tif (options.verbose) {\n\t\t\t\t\tp.log.info(`Cache hit: ${chalk.dim(cacheFile)} (fingerprint ${highlight(fingerprint)})`);\n\t\t\t\t}\n\t\t\t\tconst duration = ((Date.now() - startTime) / 1000).toFixed(1);\n\t\t\t\tp.outro(`Up to date (${duration}s)`);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (options.verbose) {\n\t\t\t\tp.log.info(`No cache for fingerprint ${highlight(fingerprint)} — will submit to API`);\n\t\t\t}\n\t\t}\n\n\t\tspinner.start(\"Submitting strings to Vocoder API\");\n\n\t\tconst batchResponse = await api.submitTranslation(\n\t\t\tbranch,\n\t\t\tstringEntries,\n\t\t\tconfig.targetLocales,\n\t\t\t{\n\t\t\t\trequestedMode,\n\t\t\t\trequestedMaxWaitMs: waitTimeoutMs,\n\t\t\t\tclientRunId: randomUUID(),\n\t\t\t\tforce: options.force,\n\t\t\t\t// Sync appIndustry from vocoder.config.ts to App on every push\n\t\t\t\t...(config.appIndustry ? { appIndustry: config.appIndustry } : {}),\n\t\t\t},\n\t\t\trepoIdentity ? { ...repoIdentity, commitSha } : { commitSha },\n\t\t);\n\n\t\tspinner.stop(\"Strings submitted\");\n\n\t\tconst effectiveMode =\n\t\t\tbatchResponse.effectiveMode ??\n\t\t\tresolveEffectiveModeFromPolicy({\n\t\t\t\tbranch,\n\t\t\t\trequestedMode,\n\t\t\t\tpolicy: config.syncPolicy,\n\t\t\t});\n\n\t\tif (options.verbose) {\n\t\t\tp.log.info(`Batch: ${chalk.dim(batchResponse.batchId)}`);\n\t\t\tp.log.info(`Requested mode: ${requestedMode}`);\n\t\t\tp.log.info(`Effective mode: ${effectiveMode}`);\n\t\t\tp.log.info(`Wait timeout: ${waitTimeoutMs}ms`);\n\t\t\tif (batchResponse.queueStatus) {\n\t\t\t\tp.log.info(`Queue status: ${batchResponse.queueStatus}`);\n\t\t\t}\n\t\t}\n\n\t\tif (batchResponse.status === \"UP_TO_DATE\" && batchResponse.noChanges) {\n\t\t\tp.log.success(`Up to date — ${highlight(batchResponse.totalStrings)} strings, no changes`);\n\t\t} else if (batchResponse.newStrings === 0) {\n\t\t\tconst archivedNote =\n\t\t\t\tbatchResponse.deletedStrings && batchResponse.deletedStrings > 0\n\t\t\t\t\t? `, ${chalk.yellow(batchResponse.deletedStrings)} archived`\n\t\t\t\t\t: \"\";\n\t\t\tp.log.success(`No new strings — ${highlight(batchResponse.totalStrings)} total${archivedNote}, using existing translations`);\n\t\t} else {\n\t\t\tconst statParts = [`${highlight(batchResponse.newStrings)} new, ${highlight(batchResponse.totalStrings)} total`];\n\t\t\tif (batchResponse.deletedStrings && batchResponse.deletedStrings > 0) {\n\t\t\t\tstatParts.push(`${chalk.yellow(batchResponse.deletedStrings)} archived`);\n\t\t\t}\n\t\t\tconst estTime = batchResponse.estimatedTime ? ` (~${batchResponse.estimatedTime}s)` : \"\";\n\t\t\tp.log.info(`${statParts.join(\", \")} → syncing to ${config.targetLocales.join(\", \")}${estTime}`);\n\t\t}\n\n\t\tlet artifacts: TranslationArtifacts | null = null;\n\t\tif (batchResponse.translations) {\n\t\t\tartifacts = {\n\t\t\t\tsource: \"fresh\",\n\t\t\t\ttranslations: batchResponse.translations,\n\t\t\t};\n\t\t}\n\n\t\tlet waitError: Error | null = null;\n\t\tif (\n\t\t\t!artifacts &&\n\t\t\t(effectiveMode === \"required\" || effectiveMode === \"best-effort\")\n\t\t) {\n\t\t\tconst waitTimeoutSecs = Math.round(waitTimeoutMs / 1000);\n\t\t\tspinner.start(`Waiting for translations (max ${waitTimeoutSecs}s)`);\n\n\t\t\tlet lastProgress = 0;\n\t\t\ttry {\n\t\t\t\tconst completion = await api.waitForCompletion(\n\t\t\t\t\tbatchResponse.batchId,\n\t\t\t\t\twaitTimeoutMs,\n\t\t\t\t\t(progress) => {\n\t\t\t\t\t\tconst percent = Math.round(progress * 100);\n\t\t\t\t\t\tif (percent > lastProgress) {\n\t\t\t\t\t\t\tspinner.message(`Translating... ${percent}%`);\n\t\t\t\t\t\t\tlastProgress = percent;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tartifacts = {\n\t\t\t\t\tsource: \"fresh\",\n\t\t\t\t\ttranslations: completion.translations,\n\t\t\t\t\tlocaleMetadata: completion.localeMetadata,\n\t\t\t\t};\n\t\t\t\tspinner.stop(\"Translations complete\");\n\t\t\t} catch (error) {\n\t\t\t\tspinner.stop(\"Translation wait incomplete\");\n\t\t\t\twaitError = error instanceof Error ? error : new Error(String(error));\n\n\t\t\t\tif (effectiveMode === \"required\") {\n\t\t\t\t\tthrow waitError;\n\t\t\t\t}\n\n\t\t\t\tp.log.warn(`Best-effort wait ended early: ${waitError.message}`);\n\t\t\t}\n\t\t}\n\n\t\tif (!artifacts) {\n\t\t\tif (mergedConfig.noFallback) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Fresh translations are not available and fallback is disabled (--no-fallback).\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tspinner.start(\"Loading fallback translations\");\n\n\t\t\tconst localFallback = readLocalCache({\n\t\t\t\tprojectRoot,\n\t\t\t\tfingerprint,\n\t\t\t});\n\n\t\t\tif (localFallback) {\n\t\t\t\tartifacts = localFallback;\n\t\t\t\tspinner.stop(`Using local cached snapshot (${fingerprint})`);\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst apiSnapshot = await fetchApiSnapshot(api, {\n\t\t\t\t\t\tbranch,\n\t\t\t\t\t\ttargetLocales: config.targetLocales,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (apiSnapshot) {\n\t\t\t\t\t\tartifacts = apiSnapshot;\n\t\t\t\t\t\tspinner.stop(\"Using latest completed API snapshot\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tspinner.stop(\"No completed API snapshot available\");\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tspinner.stop(\"Failed to fetch API snapshot\");\n\t\t\t\t\tif (options.verbose) {\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t\t: \"Unknown snapshot fetch error\";\n\t\t\t\t\t\tp.log.warn(`Snapshot fetch error: ${message}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!artifacts) {\n\t\t\t\tif (waitError) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`No fallback snapshot available after wait failure: ${waitError.message}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"No fallback snapshot available. Try again shortly or run with --mode required.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst finalTranslations = normalizeTranslations({\n\t\t\tsourceLocale: config.sourceLocale,\n\t\t\ttargetLocales: config.targetLocales,\n\t\t\tsourceStrings,\n\t\t\ttranslations: artifacts.translations,\n\t\t});\n\n\t\ttry {\n\t\t\tconst data = buildTranslationData({\n\t\t\t\tsourceLocale: config.sourceLocale,\n\t\t\t\ttargetLocales: config.targetLocales,\n\t\t\t\tstringEntries,\n\t\t\t\ttranslations: finalTranslations,\n\t\t\t\tlocaleMetadata: artifacts.localeMetadata,\n\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t});\n\t\t\tconst cachePath = writeCache({ projectRoot, fingerprint, data });\n\t\t\tif (options.verbose) {\n\t\t\t\tp.log.info(`Cache written: ${cachePath}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (options.verbose) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : \"Unknown cache write error\";\n\t\t\t\tp.log.warn(`Failed to write cache: ${message}`);\n\t\t\t}\n\t\t}\n\n\t\tif (artifacts.source !== \"fresh\") {\n\t\t\tconst sourceLabel =\n\t\t\t\tartifacts.source === \"local-cache\"\n\t\t\t\t\t? \"local cached snapshot\"\n\t\t\t\t\t: \"completed API snapshot\";\n\t\t\tp.log.warn(\n\t\t\t\t`Using ${sourceLabel}. New strings may appear after the background sync completes.`,\n\t\t\t);\n\t\t}\n\n\t\tconst duration = ((Date.now() - startTime) / 1000).toFixed(1);\n\t\tp.outro(`Sync complete! (${duration}s)`);\n\t\treturn 0;\n\t} catch (error) {\n\t\tspinner.stop();\n\n\t\tif (error instanceof VocoderAPIError && error.syncPolicyError) {\n\t\t\tp.log.error(error.syncPolicyError.message);\n\t\t\tconst guidance = getSyncPolicyErrorGuidance(error.syncPolicyError);\n\t\t\tfor (const line of guidance) {\n\t\t\t\tp.log.info(line);\n\t\t\t}\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (error instanceof VocoderAPIError && error.limitError) {\n\t\t\tconst { limitError } = error;\n\t\t\tp.log.error(limitError.message);\n\t\t\tconst guidance = getLimitErrorGuidance(limitError);\n\t\t\tfor (const line of guidance) {\n\t\t\t\tp.log.info(line);\n\t\t\t}\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (error instanceof Error) {\n\t\t\tp.log.error(error.message);\n\n\t\t\tconst isInvalidKey =\n\t\t\t\terror.message.toLowerCase().includes(\"invalid api key\") ||\n\t\t\t\t(error instanceof VocoderAPIError && error.status === 401);\n\n\t\t\tif (isInvalidKey) {\n\t\t\t\tp.log.warn(\n\t\t\t\t\t\"API key rejected — the project may have been deleted or the key revoked.\",\n\t\t\t\t);\n\t\t\t\tp.log.info(\n\t\t\t\t\t\" Run `npx @vocoder/cli init` to create a new project and key.\",\n\t\t\t\t);\n\t\t\t} else if (error.message.includes(\"git branch\")) {\n\t\t\t\tp.log.warn(\"Run from a git repository, or use:\");\n\t\t\t\tp.log.info(\" vocoder sync --branch main\");\n\t\t\t}\n\n\t\t\tif (options.verbose) {\n\t\t\t\tp.log.info(`Full error: ${error.stack ?? error}`);\n\t\t\t}\n\t\t}\n\n\t\treturn 1;\n\t}\n}\n","import { execSync } from \"node:child_process\";\n\nconst REGEX_SPECIAL_CHARS = /[.+?^${}()|[\\]\\\\]/g;\n\nfunction escapeRegexChar(value: string): string {\n\treturn value.replace(REGEX_SPECIAL_CHARS, \"\\\\$&\");\n}\n\n/**\n * Detects the current git branch from multiple sources in priority order:\n * 1. Explicit --branch flag (passed as parameter)\n * 2. CI environment variables (GitHub Actions, Vercel, Netlify, etc.)\n * 3. Git command (local development)\n *\n * @param override - Optional branch name to override detection\n * @returns The current branch name\n */\nexport function detectBranch(override?: string): string {\n\t// 1. Explicit override (from --branch flag)\n\tif (override) {\n\t\treturn override;\n\t}\n\n\t// 2. CI environment variables\n\tconst envBranch =\n\t\tprocess.env.GITHUB_HEAD_REF || // GitHub Actions (PR source branch)\n\t\tprocess.env.GITHUB_REF_NAME || // GitHub Actions (push)\n\t\tprocess.env.VERCEL_GIT_COMMIT_REF || // Vercel\n\t\tprocess.env.BRANCH || // Netlify\n\t\tprocess.env.CF_PAGES_BRANCH || // Cloudflare Pages\n\t\tprocess.env.CI_COMMIT_REF_NAME || // GitLab CI\n\t\tprocess.env.BITBUCKET_BRANCH || // Bitbucket Pipelines\n\t\tprocess.env.CIRCLE_BRANCH || // CircleCI\n\t\tprocess.env.RENDER_GIT_BRANCH; // Render\n\n\tif (envBranch) {\n\t\treturn envBranch;\n\t}\n\n\t// 3. Git command (local development)\n\ttry {\n\t\tconst branch = execSync(\"git rev-parse --abbrev-ref HEAD\", {\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\t}).trim();\n\n\t\treturn branch;\n\t} catch (_error) {\n\t\tthrow new Error(\n\t\t\t\"Failed to detect git branch. Make sure you are in a git repository or set the --branch flag.\",\n\t\t);\n\t}\n}\n\n/**\n * Checks if the current branch is a target branch that should trigger translations\n *\n * @param currentBranch - The current branch name\n * @param targetBranches - List of branches that should trigger translations\n * @returns True if the branch should trigger translations\n */\nexport function isTargetBranch(\n\tcurrentBranch: string,\n\ttargetBranches: string[],\n): boolean {\n\treturn targetBranches.some((pattern) =>\n\t\tmatchBranchPattern(currentBranch, pattern),\n\t);\n}\n\nexport function matchBranchPattern(branch: string, pattern: string): boolean {\n\tconst trimmedPattern = pattern.trim();\n\tif (!trimmedPattern) {\n\t\treturn false;\n\t}\n\n\tlet regexSource = \"^\";\n\tfor (let i = 0; i < trimmedPattern.length; i += 1) {\n\t\tconst char = trimmedPattern[i];\n\t\tif (!char) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"*\") {\n\t\t\tconst next = trimmedPattern[i + 1];\n\t\t\tif (next === \"*\") {\n\t\t\t\tregexSource += \".*\";\n\t\t\t\ti += 1;\n\t\t\t} else {\n\t\t\t\tregexSource += \"[^/]*\";\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tregexSource += escapeRegexChar(char);\n\t}\n\tregexSource += \"$\";\n\n\treturn new RegExp(regexSource).test(branch);\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"./theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { loadVocoderConfig } from \"@vocoder/extractor\";\nimport type {\n\tLocalConfig,\n\tRequestedSyncMode,\n\tTranslateOptions,\n} from \"../types.js\";\n\n// Load .env file if present\nloadEnv();\n\n/**\n * Validates the local configuration\n */\nexport function validateLocalConfig(config: LocalConfig): void {\n\tif (!config.apiKey || config.apiKey.length === 0) {\n\t\tthrow new Error(\"VOCODER_API_KEY is required. Set it in your .env file.\");\n\t}\n\n\tif (!config.apiKey.startsWith(\"vca_\")) {\n\t\tthrow new Error(\n\t\t\t\"Invalid API key format. Expected an app API key starting with vca_.\",\n\t\t);\n\t}\n\n\tif (!config.apiUrl || !config.apiUrl.startsWith(\"http\")) {\n\t\tthrow new Error(\"Invalid API URL\");\n\t}\n}\n\n/**\n * Merge configuration from all sources with priority:\n * 1. CLI flags (highest priority)\n * 2. Environment variables\n * 3. Defaults (lowest priority)\n *\n * @param cliOptions - Options from CLI flags\n * @param verbose - Whether to log config sources\n * @returns Merged configuration with source information\n */\nexport async function getMergedConfig(\n\tcliOptions: TranslateOptions,\n\tverbose: boolean = false,\n\t_startDir?: string,\n): Promise<{\n\tincludePattern: string[];\n\texcludePattern: string[];\n\tapiKey?: string;\n\tapiUrl?: string;\n\tmode: RequestedSyncMode;\n\tmaxWaitMs?: number;\n\tnoFallback: boolean;\n\tconfigSources: {\n\t\tincludePattern: string;\n\t\texcludePattern: string;\n\t\tapiKey: string;\n\t\tapiUrl: string;\n\t\tmode: string;\n\t\tmaxWaitMs: string;\n\t\tnoFallback: string;\n\t};\n}> {\n\tconst configSources = {\n\t\tincludePattern: \"default\",\n\t\texcludePattern: \"default\",\n\t\tapiKey: \"environment\",\n\t\tapiUrl: \"default\",\n\t\tmode: \"default\",\n\t\tmaxWaitMs: \"default\",\n\t\tnoFallback: \"default\",\n\t};\n\n\t// 1. Defaults\n\tconst defaults = {\n\t\tincludePattern: [\"**/*.{tsx,jsx,ts,js}\"],\n\t\texcludePattern: [\n\t\t\t\"**/node_modules/**\",\n\t\t\t\"**/.next/**\",\n\t\t\t\"**/.nuxt/**\",\n\t\t\t\"**/.svelte-kit/**\",\n\t\t\t\"**/.output/**\",\n\t\t\t\"**/dist/**\",\n\t\t\t\"**/build/**\",\n\t\t\t\"**/out/**\",\n\t\t\t\"**/.vite/**\",\n\t\t\t\"**/.turbo/**\",\n\t\t\t\"**/coverage/**\",\n\t\t\t\"**/.cache/**\",\n\t\t\t\"**/*.min.js\",\n\t\t\t\"**/*.min.ts\",\n\t\t\t\"**/__generated__/**\",\n\t\t\t\"**/*.test.*\",\n\t\t\t\"**/*.spec.*\",\n\t\t\t\"**/*.stories.*\",\n\t\t\t\"**/__tests__/**\",\n\t\t],\n\t\tapiUrl: \"https://vocoder.app\",\n\t};\n\n\t// 2. vocoder.config.ts — the canonical source for extraction patterns.\n\t// CLI flags still override it for one-off runs.\n\tconst fileConfig = loadVocoderConfig(process.cwd());\n\n\tif (!fileConfig) {\n\t\tp.log.warn(\n\t\t\t`No ${highlight(\"vocoder.config.ts\")} found — run ${highlight(\"npx @vocoder/cli init\")} to generate one.`,\n\t\t);\n\t}\n\n\t// 3. Environment variables (legacy, lower priority than config file)\n\tconst envExtractionPattern = process.env.VOCODER_INCLUDE_PATTERN;\n\tconst envExcludePattern = process.env.VOCODER_EXCLUDE_PATTERN;\n\tconst envApiUrl = process.env.VOCODER_API_URL;\n\tconst envSyncMode = process.env.VOCODER_SYNC_MODE;\n\tconst envSyncMaxWaitMs = process.env.VOCODER_SYNC_MAX_WAIT_MS;\n\tconst envSyncNoFallback = process.env.VOCODER_SYNC_NO_FALLBACK;\n\n\t// 4. Merge with priority: CLI flag > vocoder.config.ts > env > defaults\n\n\t// Extract patterns (include)\n\tlet includePattern: string[];\n\tif (cliOptions.include && cliOptions.include.length > 0) {\n\t\tincludePattern = cliOptions.include;\n\t\tconfigSources.includePattern = \"CLI flag\";\n\t} else if (fileConfig?.include && fileConfig.include.length > 0) {\n\t\tincludePattern = fileConfig.include;\n\t\tconfigSources.includePattern = \"vocoder.config\";\n\t} else if (envExtractionPattern) {\n\t\tincludePattern = [envExtractionPattern];\n\t\tconfigSources.includePattern = \"environment\";\n\t} else {\n\t\tincludePattern = defaults.includePattern;\n\t}\n\n\t// Exclude patterns\n\tlet excludePattern: string[];\n\tif (cliOptions.exclude && cliOptions.exclude.length > 0) {\n\t\texcludePattern = cliOptions.exclude;\n\t\tconfigSources.excludePattern = \"CLI flag\";\n\t} else if (fileConfig?.exclude && fileConfig.exclude.length > 0) {\n\t\texcludePattern = fileConfig.exclude;\n\t\tconfigSources.excludePattern = \"vocoder.config\";\n\t} else if (envExcludePattern) {\n\t\texcludePattern = envExcludePattern\n\t\t\t.split(\",\")\n\t\t\t.map((p: string) => p.trim())\n\t\t\t.filter(Boolean);\n\t\tconfigSources.excludePattern = \"environment\";\n\t} else {\n\t\texcludePattern = defaults.excludePattern;\n\t}\n\n\t// API key (from env)\n\tlet apiKey: string | undefined;\n\tif (process.env.VOCODER_API_KEY) {\n\t\tapiKey = process.env.VOCODER_API_KEY;\n\t\tconfigSources.apiKey = \"environment\";\n\t}\n\n\t// API URL\n\tlet apiUrl: string;\n\tif (envApiUrl) {\n\t\tapiUrl = envApiUrl;\n\t\tconfigSources.apiUrl = \"environment\";\n\t} else {\n\t\tapiUrl = defaults.apiUrl;\n\t}\n\n\tconst modeCandidates = [\"auto\", \"required\", \"best-effort\"] as const;\n\tlet mode: RequestedSyncMode = \"auto\";\n\tif (cliOptions.mode && modeCandidates.includes(cliOptions.mode)) {\n\t\tmode = cliOptions.mode;\n\t\tconfigSources.mode = \"CLI flag\";\n\t} else if (\n\t\tenvSyncMode &&\n\t\tmodeCandidates.includes(envSyncMode as RequestedSyncMode)\n\t) {\n\t\tmode = envSyncMode as RequestedSyncMode;\n\t\tconfigSources.mode = \"environment\";\n\t}\n\n\tlet maxWaitMs: number | undefined;\n\tif (\n\t\ttypeof cliOptions.maxWaitMs === \"number\" &&\n\t\tNumber.isFinite(cliOptions.maxWaitMs) &&\n\t\tcliOptions.maxWaitMs > 0\n\t) {\n\t\tmaxWaitMs = Math.floor(cliOptions.maxWaitMs);\n\t\tconfigSources.maxWaitMs = \"CLI flag\";\n\t} else if (envSyncMaxWaitMs) {\n\t\tconst parsed = Number.parseInt(envSyncMaxWaitMs, 10);\n\t\tif (Number.isFinite(parsed) && parsed > 0) {\n\t\t\tmaxWaitMs = parsed;\n\t\t\tconfigSources.maxWaitMs = \"environment\";\n\t\t}\n\t}\n\n\tlet noFallback = false;\n\tif (typeof cliOptions.noFallback === \"boolean\") {\n\t\tnoFallback = cliOptions.noFallback;\n\t\tconfigSources.noFallback = \"CLI flag\";\n\t} else if (envSyncNoFallback) {\n\t\tnoFallback = [\"1\", \"true\", \"yes\", \"on\"].includes(\n\t\t\tenvSyncNoFallback.toLowerCase(),\n\t\t);\n\t\tconfigSources.noFallback = \"environment\";\n\t}\n\n\t// Log config sources in verbose mode\n\tif (verbose) {\n\t\tconst lines = [\n\t\t\t`Include patterns: ${highlight(configSources.includePattern)}`,\n\t\t\t...(excludePattern.length > 0\n\t\t\t\t? [`Exclude patterns: ${highlight(configSources.excludePattern)}`]\n\t\t\t\t: []),\n\t\t\t`API key: ${highlight(configSources.apiKey)}`,\n\t\t\t`API URL: ${highlight(configSources.apiUrl)}`,\n\t\t\t`Sync mode: ${highlight(configSources.mode)}`,\n\t\t\t...(maxWaitMs\n\t\t\t\t? [`Max wait: ${highlight(String(configSources.maxWaitMs))}`]\n\t\t\t\t: []),\n\t\t\t`No fallback: ${highlight(String(configSources.noFallback))}`,\n\t\t];\n\t\tp.note(lines.join(\"\\n\"), \"Configuration sources\");\n\t}\n\n\treturn {\n\t\tincludePattern,\n\t\texcludePattern,\n\t\tapiKey,\n\t\tapiUrl,\n\t\tmode,\n\t\tmaxWaitMs,\n\t\tnoFallback,\n\t\tconfigSources,\n\t};\n}\n","import * as p from \"@clack/prompts\";\nimport { VocoderAPI } from \"../utils/api.js\";\nimport { clearAuthData, readAuthData } from \"../utils/auth-store.js\";\n\nexport interface LogoutOptions {\n\tapiUrl?: string;\n}\n\nexport async function logout(options: LogoutOptions = {}): Promise<number> {\n\tconst stored = readAuthData();\n\n\tif (!stored) {\n\t\tp.log.info(\"Not currently authenticated.\");\n\t\treturn 0;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? stored.apiUrl ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\n\ttry {\n\t\tawait api.revokeCliToken(stored.token);\n\t} catch {\n\t\t// Ignore errors — we still clear local data even if the server call fails\n\t}\n\n\tclearAuthData();\n\tp.log.success(`Logged out (was ${stored.email})`);\n\treturn 0;\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI } from \"../utils/api.js\";\n\nloadEnv();\n\nexport interface AppConfigOptions {\n\tapiUrl?: string;\n}\n\n/**\n * Displays the current Vocoder app configuration.\n *\n * Shows: project name, organization, source locale, target locales,\n * target branches, primary branch, and sync policy settings.\n *\n * Reads the app API key from VOCODER_API_KEY.\n * Endpoint: GET /api/cli/config\n *\n * @throws If VOCODER_API_KEY is missing or invalid.\n */\nexport async function appConfig(options: AppConfigOptions = {}): Promise<number> {\n\tconst apiKey = process.env.VOCODER_API_KEY;\n\tif (!apiKey) {\n\t\tp.log.error(\n\t\t\t\"VOCODER_API_KEY is not set. Run `npx @vocoder/cli init` to set up your project.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiKey, apiUrl });\n\n\ttry {\n\t\tconst config = await api.getAppConfig();\n\n\t\tconst lines = [\n\t\t\t`App: ${chalk.bold(config.projectName)}`,\n\t\t\t`Organization: ${config.organizationName}`,\n\t\t\t`Source locale: ${highlight(config.sourceLocale)}`,\n\t\t\t`Target locales: ${\n\t\t\t\tconfig.targetLocales.length > 0\n\t\t\t\t\t? config.targetLocales.map((l) => highlight(l)).join(\", \")\n\t\t\t\t\t: chalk.dim(\"(none)\")\n\t\t\t}`,\n\t\t\t`Target branches: ${config.targetBranches.map((b) => highlight(b)).join(\", \")}`,\n\t\t\t...(config.primaryBranch\n\t\t\t\t? [`Primary branch: ${highlight(config.primaryBranch)}`]\n\t\t\t\t: []),\n\t\t\t`Sync policy:`,\n\t\t\t` Blocking branches: ${config.syncPolicy.blockingBranches.map((b) => highlight(b)).join(\", \")}`,\n\t\t\t` Blocking mode: ${highlight(config.syncPolicy.blockingMode)}`,\n\t\t\t` Non-blocking mode: ${highlight(config.syncPolicy.nonBlockingMode)}`,\n\t\t\t` Max wait: ${highlight(String(config.syncPolicy.defaultMaxWaitMs))} ms`,\n\t\t];\n\n\t\tp.note(lines.join(\"\\n\"), `${config.projectName} — app config`);\n\t\treturn 0;\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to fetch project config.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI } from \"../utils/api.js\";\nimport { detectBranch } from \"../utils/branch.js\";\n\nloadEnv();\n\nexport interface TranslationsOptions {\n\t/** Git branch. Auto-detected from git/CI env if omitted. */\n\tbranch?: string;\n\t/** Specific target locale to fetch. All configured locales if omitted. */\n\tlocale?: string;\n\t/**\n\t * Output directory for locale JSON files.\n\t * When set, writes one <locale>.json per locale to this directory.\n\t * When omitted, prints the full snapshot as JSON to stdout.\n\t */\n\toutput?: string;\n\tapiUrl?: string;\n}\n\n/**\n * Downloads the current translation snapshot for the project.\n *\n * With --output <dir>: writes one <locale>.json file per locale to the\n * specified directory. Each file shape: { \"source text\": \"translated text\" }.\n *\n * Without --output: prints the full snapshot JSON to stdout, suitable\n * for piping or programmatic use.\n *\n * Reads the project API key from VOCODER_API_KEY.\n * Endpoint: GET /api/cli/sync/snapshot\n *\n * @param options.branch Git branch (auto-detected from git/CI if omitted).\n * @param options.locale Specific target locale; all configured locales if omitted.\n * @param options.output Output directory. Omit to print to stdout.\n *\n * @throws If VOCODER_API_KEY is missing or invalid.\n */\nexport async function getTranslations(options: TranslationsOptions = {}): Promise<number> {\n\tconst apiKey = process.env.VOCODER_API_KEY;\n\tif (!apiKey) {\n\t\tp.log.error(\n\t\t\t\"VOCODER_API_KEY is not set. Run `npx @vocoder/cli init` to set up your project.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiKey, apiUrl });\n\n\tlet branch: string;\n\ttry {\n\t\tbranch = detectBranch(options.branch);\n\t} catch (error) {\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Failed to detect branch.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst spinner = p.spinner();\n\tspinner.start(`Fetching translations for ${highlight(branch)}…`);\n\n\ttry {\n\t\t// Fetch the project config to resolve which target locales to request\n\t\tconst projectConfig = await api.getAppConfig();\n\t\tconst targetLocales = options.locale\n\t\t\t? [options.locale]\n\t\t\t: projectConfig.targetLocales;\n\n\t\tif (targetLocales.length === 0) {\n\t\t\tspinner.stop(\"No target locales configured.\");\n\t\t\tp.log.info(\"Add target locales with `vocoder locales add <code>`.\");\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst snapshot = await api.getTranslationSnapshot({ branch, targetLocales });\n\t\tspinner.stop(`Fetched translations for ${highlight(branch)}`);\n\n\t\tif (snapshot.status === \"NOT_FOUND\") {\n\t\t\tp.log.warn(\n\t\t\t\t`No translation snapshot found for branch \"${branch}\". ` +\n\t\t\t\t\t\"Run `vocoder sync` to generate one.\",\n\t\t\t);\n\t\t\treturn 1;\n\t\t}\n\n\t\tconst translations = snapshot.translations ?? {};\n\n\t\tif (options.output) {\n\t\t\twriteLocaleFiles(translations, options.output);\n\t\t} else {\n\t\t\t// stdout — raw JSON for piping/programmatic use\n\t\t\tprocess.stdout.write(JSON.stringify(translations, null, 2));\n\t\t\tprocess.stdout.write(\"\\n\");\n\t\t}\n\n\t\treturn 0;\n\t} catch (error) {\n\t\tspinner.stop(\"Failed to fetch translations.\");\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Unknown error.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n\n/**\n * Writes one <locale>.json file per locale to the output directory.\n * Creates the directory if it does not exist.\n * Each file shape: { \"source text\": \"translated text\" }\n */\nfunction writeLocaleFiles(\n\ttranslations: Record<string, Record<string, string>>,\n\toutputDir: string,\n): void {\n\tmkdirSync(outputDir, { recursive: true });\n\n\tfor (const [locale, strings] of Object.entries(translations)) {\n\t\tconst filePath = join(outputDir, `${locale}.json`);\n\t\twriteFileSync(filePath, JSON.stringify(strings, null, 2) + \"\\n\", \"utf-8\");\n\t\tp.log.success(`Wrote ${highlight(filePath)}`);\n\t}\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { active, highlight } from \"../utils/theme.js\";\nimport { config as loadEnv } from \"dotenv\";\nimport { VocoderAPI, VocoderAPIError } from \"../utils/api.js\";\nimport { readAuthData } from \"../utils/auth-store.js\";\nimport { resolveGitRepositoryIdentity } from \"../utils/git-identity.js\";\nimport { getLimitErrorGuidance } from \"./sync.js\";\n\nloadEnv();\n\nexport interface CreateAppOptions {\n\t/** Project display name (required). */\n\tname: string;\n\t/** BCP 47 source locale code, e.g. \"en\" (required). */\n\tsourceLocale: string;\n\t/** Comma-separated target locale codes, e.g. \"fr,de,pt-BR\". */\n\ttargetLocales?: string;\n\t/** Comma-separated branch names to enable sync on. Defaults to \"main\". */\n\ttargetBranches?: string;\n\t/** Organization ID of the workspace to create the project in (required). */\n\tworkspace: string;\n\t/**\n\t * Explicit git repository canonical, e.g. \"github:owner/repo\".\n\t * Auto-detected from git remote if omitted.\n\t */\n\trepo?: string;\n\t/**\n\t * App directory within the repository for monorepos, e.g. \"apps/web\".\n\t * Defaults to \".\" (repo root).\n\t */\n\tappDir?: string;\n\tapiUrl?: string;\n}\n\n/**\n * Creates a new Vocoder project without the interactive init flow.\n *\n * Requires a valid user token in the local auth store (run `vocoder init` first).\n * Prints the generated VOCODER_API_KEY to stdout on success.\n *\n * Git identity is auto-detected from the git remote. The detected repository\n * must be accessible via the workspace's GitHub App installation for\n * push-based sync to function. Use --repo to override auto-detection, or\n * omit repo binding entirely if not in a git repository.\n *\n * Endpoint: POST /api/cli/projects\n *\n * @param options.name Project display name (required).\n * @param options.sourceLocale Source language BCP 47 code (required).\n * @param options.targetLocales Comma-separated target locale codes.\n * @param options.targetBranches Comma-separated branch names (default: \"main\").\n * @param options.workspace Organization ID (required).\n * @param options.repo Git repo canonical override.\n * @param options.appDir App directory for monorepos (default: \".\").\n *\n * @throws If user token is missing, workspace is invalid, or the plan's\n * maxProjects limit is exceeded.\n */\nexport async function createApp(options: CreateAppOptions): Promise<number> {\n\tconst authData = readAuthData();\n\tif (!authData) {\n\t\tp.log.error(\n\t\t\t\"Not logged in. Run `npx @vocoder/cli init` to authenticate first.\",\n\t\t);\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? process.env.VOCODER_API_URL ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiKey: \"\", apiUrl });\n\n\t// Resolve repo identity — auto-detect if not overridden\n\tlet repoCanonical: string | undefined;\n\tlet appDir = options.appDir ?? \".\";\n\n\tif (options.repo) {\n\t\trepoCanonical = options.repo;\n\t} else {\n\t\tconst identity = resolveGitRepositoryIdentity();\n\t\tif (identity) {\n\t\t\trepoCanonical = identity.repoCanonical;\n\t\t\t// Only override appDir from git if the caller didn't specify one\n\t\t\tif (!options.appDir && identity.repoAppDir) {\n\t\t\t\tappDir = identity.repoAppDir;\n\t\t\t}\n\t\t} else {\n\t\t\tp.log.warn(\n\t\t\t\t\"Could not detect a git remote. The project will be created without repo binding — \" +\n\t\t\t\t\t\"sync-on-push will not function until a repository is connected via the Vocoder dashboard.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tconst targetLocales = options.targetLocales\n\t\t? options.targetLocales.split(\",\").map((l) => l.trim()).filter(Boolean)\n\t\t: [];\n\n\tconst targetBranches = options.targetBranches\n\t\t? options.targetBranches.split(\",\").map((b) => b.trim()).filter(Boolean)\n\t\t: [\"main\"];\n\n\tconst spinner = p.spinner();\n\tspinner.start(`Creating app \"${options.name}\"…`);\n\n\ttry {\n\t\tconst result = await api.createProject(authData.token, {\n\t\t\torganizationId: options.workspace,\n\t\t\tname: options.name,\n\t\t\tsourceLocale: options.sourceLocale,\n\t\t\ttargetLocales,\n\t\t\ttargetBranches,\n\t\t\tappDirs: [appDir],\n\t\t\t...(repoCanonical ? { repoCanonical } : {}),\n\t\t});\n\n\t\tspinner.stop(`Created app ${chalk.bold(result.projectName)}`);\n\n\t\tconst lines = [\n\t\t\t`Project ID: ${result.projectId}`,\n\t\t\t`Source locale: ${highlight(result.sourceLocale)}`,\n\t\t\t`Target locales: ${result.targetLocales.length > 0 ? result.targetLocales.map((l) => highlight(l)).join(\", \") : chalk.dim(\"(none)\")}`,\n\t\t\t`Branches: ${result.targetBranches.map((b) => highlight(b)).join(\", \")}`,\n\t\t\t...(repoCanonical\n\t\t\t\t? [`Repository: ${highlight(repoCanonical)}${appDir !== \".\" ? ` (${appDir})` : \"\"}`]\n\t\t\t\t: []),\n\t\t\t\"\",\n\t\t\t`Add this to your .env file:`,\n\t\t\t` ${chalk.bold(\"VOCODER_API_KEY\")}=${highlight(result.apiKey)}`,\n\t\t];\n\n\t\tp.note(lines.join(\"\\n\"), \"Project created\");\n\n\t\tif (!result.repositoryBound && repoCanonical) {\n\t\t\tp.log.warn(\n\t\t\t\t`Repository \"${repoCanonical}\" was not automatically connected. ` +\n\t\t\t\t\t\"Ensure your GitHub App installation covers this repository.\",\n\t\t\t);\n\t\t}\n\n\t\treturn 0;\n\t} catch (error) {\n\t\tspinner.stop(\"Failed to create project.\");\n\n\t\tif (error instanceof VocoderAPIError && error.limitError) {\n\t\t\tconst { limitError } = error;\n\t\t\tp.log.error(limitError.message);\n\t\t\tfor (const line of getLimitErrorGuidance(limitError)) {\n\t\t\t\tp.log.info(line);\n\t\t\t}\n\t\t\treturn 1;\n\t\t}\n\n\t\tp.log.error(\n\t\t\terror instanceof Error ? error.message : \"Unknown error.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { VocoderAPI } from \"../utils/api.js\";\nimport { readAuthData } from \"../utils/auth-store.js\";\n\nexport interface WhoamiOptions {\n\tapiUrl?: string;\n}\n\nexport async function whoami(options: WhoamiOptions = {}): Promise<number> {\n\tconst stored = readAuthData();\n\n\tif (!stored) {\n\t\tp.log.info(\"Not logged in. Run `vocoder init` to authenticate.\");\n\t\treturn 1;\n\t}\n\n\tconst apiUrl = options.apiUrl ?? stored.apiUrl ?? \"https://vocoder.app\";\n\tconst api = new VocoderAPI({ apiUrl, apiKey: \"\" });\n\n\ttry {\n\t\tconst info = await api.getCliUserInfo(stored.token);\n\t\tp.log.info(`Logged in as ${chalk.bold(info.email)}`);\n\t\tif (info.name) {\n\t\t\tp.log.info(`Name: ${info.name}`);\n\t\t}\n\t\tp.log.info(`API: ${apiUrl}`);\n\t\treturn 0;\n\t} catch {\n\t\tp.log.error(\n\t\t\t\"Stored credentials are invalid or expired. Run `vocoder init` to re-authenticate.\",\n\t\t);\n\t\treturn 1;\n\t}\n}\n"],"mappings":"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","names":["p","execSync","spawn","existsSync","writeFileSync","p","URL","resolve","resolve","p","chalk","isCancel","chalk","isCancel","isCancel","Prompt","p","S_BAR","S_BAR_END","S_ACTIVE","S_SUBMIT","S_CANCEL","S_ERROR","symbol","MAX_VISIBLE","buildList","Prompt","isCancel","chalk","chalk","join","execSync","p","chalk","resolve","tryOpenBrowser","spawn","chalk","execSync","join","existsSync","writeFileSync","anonApi","spinner","options","p","chalk","loadEnv","existsSync","readFileSync","writeFileSync","join","p","chalk","execSync","p","loadEnv","loadEnv","p","join","existsSync","readFileSync","writeFileSync","lines","spinner","chalk","duration","loadEnv","spinner","chalk","p","p","chalk","loadEnv","loadEnv","chalk","mkdirSync","writeFileSync","join","p","loadEnv","loadEnv","spinner","mkdirSync","join","writeFileSync","p","chalk","loadEnv","loadEnv","spinner","chalk","p","chalk","info","chalk"]}
|