@ai-translate/cli 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,15 +56,25 @@ This is how a provider API key normally reaches your config, for example `apiKey
56
56
 
57
57
  ### `init`
58
58
 
59
- Detects the project's Next.js localization setup and writes `ai-translate.config.ts` for it. This is the only command that runs without an existing config.
59
+ Detects the project's localization resources and writes `ai-translate.config.ts`. This is the only command that runs without an existing config.
60
60
 
61
61
  ```bash
62
62
  ai-translate init
63
63
  ai-translate init --preview
64
64
  ai-translate init --integration i18next
65
+ ai-translate init --integration apple --preview
65
66
  ```
66
67
 
67
- Recognises **next-intl** and **i18next** (including `react-i18next` and `next-i18next`), inferring the message layout, the locale list, and the source locale, then printing the evidence behind each conclusion.
68
+ Recognises **next-intl**, **i18next** (including Expo/React Native projects using `react-i18next`), and **Apple localization** (`.xcstrings` catalogs and `.lproj/*.strings` tables). Detection infers source and target languages from resources and Xcode settings and prints the evidence behind each conclusion. Multiple native resource roots become one configuration.
69
+
70
+ For an Xcode or Apple Swift package project without resources, `init` writes a starter config with explicit extraction instructions. Create and populate a String Catalog with Xcode, then configure your target languages. `init` does not extract hardcoded Swift, JavaScript, or Rust text and never invents target languages. Expo and Tauri projects without localization resources must externalize their text first.
71
+
72
+ Native configs use explicit file includes; an empty starter uses `include: []`.
73
+ After creating or repairing resources, review `init --preview` and update the
74
+ includes. Detection partitions mixed Base/source tables, reports neighboring
75
+ projects with different source languages, and excludes generated native output.
76
+
77
+ Custom detectors use the platform-neutral `@ai-translate/integrations` interfaces. Adapter plans declare the package, factory export, and literal options, so adding a platform does not require changing the CLI's config renderer. `@ai-translate/next` retains its existing detection APIs for compatibility.
68
78
 
69
79
  It writes exactly one file and nothing else. Installing packages, setting `OPENAI_API_KEY`, and reviewing the model choice are printed as next steps rather than done for you, so running it against an unfamiliar repository is safe.
70
80
 
@@ -88,6 +98,10 @@ ai-translate sync --locale de --catalog messages
88
98
 
89
99
  Writes happen inside a staged transaction: files and state are committed together only if the run converges, so an interrupted or failing sync leaves your content untouched. When semantic audits reject a translation, the run retries it up to `validation.semanticRepairAttempts` times before failing.
90
100
 
101
+ Before committing, the CLI verifies that live files still match the snapshots it
102
+ staged. If a developer or Xcode saved a file during translation, the run aborts
103
+ without replacing those edits. Rerun to translate from the updated resources.
104
+
91
105
  Exits non-zero if any entry failed, if audits did not converge, or if a `--dry-run` exceeded the configured `validation.dryRunBudget`.
92
106
 
93
107
  ### `check`
package/dist/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as runCli } from "./src-Cnnq284f.mjs";
2
+ import { n as runCli } from "./src-Bb6vfpFm.mjs";
3
3
  //#region src/bin.ts
4
4
  const exitCode = await runCli();
5
5
  process.exit(exitCode);
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as loadEnvFiles, i as loadConfig, n as runCli, r as findConfigPath, t as defineConfig } from "./src-Cnnq284f.mjs";
1
+ import { a as loadEnvFiles, i as loadConfig, n as runCli, r as findConfigPath, t as defineConfig } from "./src-Bb6vfpFm.mjs";
2
2
  export { defineConfig, findConfigPath, loadConfig, loadEnvFiles, runCli };
@@ -4,7 +4,9 @@ import { existsSync, promises } from "node:fs";
4
4
  import * as path from "node:path";
5
5
  import { config, parse } from "dotenv";
6
6
  import { createJiti } from "jiti";
7
- import { detectProject, renderConfig } from "@ai-translate/next";
7
+ import { appleIntegration } from "@ai-translate/apple";
8
+ import { detectProject, renderConfig, requiredConfigPackages } from "@ai-translate/integrations";
9
+ import { builtinIntegrations } from "@ai-translate/next";
8
10
  import { randomUUID } from "node:crypto";
9
11
  import * as os from "node:os";
10
12
  import { supportsScopedSave } from "@ai-translate/core/types";
@@ -68,8 +70,8 @@ async function loadConfig(cwd, explicitPath) {
68
70
  //#region src/init.ts
69
71
  const CONFIG_FILENAME = "ai-translate.config.ts";
70
72
  const DEFAULT_AI_SDK_PACKAGE = "@ai-sdk/openai";
71
- /** Packages a generated config imports from, whichever provider it wires up. */
72
- const REQUIRED_PACKAGES = ["@ai-translate/cli", "@ai-translate/fs-json"];
73
+ /** Platforms compose independent detectors; the runner has no platform dependencies. */
74
+ const builtinInitIntegrations = [...builtinIntegrations, appleIntegration];
73
75
  function describe(setup) {
74
76
  return [
75
77
  `Detected ${setup.displayName}:`,
@@ -78,22 +80,14 @@ function describe(setup) {
78
80
  ];
79
81
  }
80
82
  async function missingPackages(cwd, plan, options) {
81
- const expected = [
82
- ...REQUIRED_PACKAGES,
83
- ...plan.messageFormat === "plain" ? [] : ["@ai-translate/message-formats"],
84
- ...options.provider === "ai-sdk" ? [
85
- "@ai-translate/provider-ai-sdk",
86
- "ai",
87
- options.providerPackage ?? DEFAULT_AI_SDK_PACKAGE
88
- ] : ["@ai-translate/provider-openai"]
89
- ];
83
+ const expected = requiredConfigPackages(plan, options);
90
84
  try {
91
85
  const raw = await promises.readFile(path.join(cwd, "package.json"), "utf8");
92
86
  const manifest = JSON.parse(raw);
93
87
  const declared = /* @__PURE__ */ new Set([...Object.keys(manifest.dependencies ?? {}), ...Object.keys(manifest.devDependencies ?? {})]);
94
88
  return expected.filter((name) => !declared.has(name));
95
89
  } catch {
96
- return expected;
90
+ return [...expected];
97
91
  }
98
92
  }
99
93
  function chooseSetup(setups, requested) {
@@ -103,7 +97,7 @@ function chooseSetup(setups, requested) {
103
97
  return match;
104
98
  }
105
99
  const [best, ...rest] = setups;
106
- if (best === void 0) throw new Error("No supported Next.js localization setup was found. ai-translate init currently recognises next-intl and i18next. Write ai-translate.config.ts by hand, or run init from the directory holding package.json and your locale files.");
100
+ if (best === void 0) throw new Error("No supported localization setup was found. ai-translate init recognises next-intl and i18next, Apple String Catalogs, localized .strings tables, and Xcode or Apple Swift package projects. For Expo, React Native, or Tauri apps with hardcoded text, first externalize strings into localization resources; init does not extract text from application code. Run init from the project root, or write ai-translate.config.ts by hand.");
107
101
  if (rest.length > 0 && rest[0]?.confidence === best.confidence) throw new Error(`Found more than one localization setup (${setups.map((setup) => setup.integrationId).join(", ")}). Re-run with --integration <id> to choose.`);
108
102
  return best;
109
103
  }
@@ -111,11 +105,11 @@ function chooseSetup(setups, requested) {
111
105
  * Detects the project's localization setup and writes a config for it.
112
106
  *
113
107
  * Nothing else is touched. Installing packages, wiring scripts, and editing the
114
- * Next.js config stay in the user's hands, so `init` on an unfamiliar repository
108
+ * application configuration stay in the user's hands, so `init` on an unfamiliar repository
115
109
  * produces exactly one new file and a list of instructions.
116
110
  */
117
111
  async function runInit(cwd, options = {}) {
118
- const setups = await detectProject(cwd, options.integrations === void 0 ? {} : { integrations: options.integrations });
112
+ const setups = await detectProject(cwd, { integrations: options.integrations ?? builtinInitIntegrations });
119
113
  const setup = chooseSetup(setups, options.integration);
120
114
  const contents = renderConfig(setup.plan, {
121
115
  ...options.model === void 0 ? {} : { model: options.model },
@@ -159,6 +153,7 @@ function cloneEntry(entry) {
159
153
  return {
160
154
  ...entry,
161
155
  address: entry.address.map((segment) => ({ ...segment })),
156
+ ...entry.context === void 0 ? {} : { context: structuredClone(entry.context) },
162
157
  ...entry.meta === void 0 ? {} : { meta: { ...entry.meta } },
163
158
  ...entry.tokens === void 0 ? {} : { tokens: entry.tokens.map((token) => ({ ...token })) }
164
159
  };
@@ -265,6 +260,12 @@ var StagedCatalogs = class {
265
260
  async promote() {
266
261
  for (const staged of this.files.values()) await writeFileAtomic(staged.realPath, await promises.readFile(staged.tempPath), staged.mode);
267
262
  }
263
+ async verifyOriginals() {
264
+ await Promise.all([...this.files.values()].map(async (staged) => {
265
+ const current = await readOriginal(staged.realPath);
266
+ if (!(current.original === null ? staged.original === null : staged.original !== null && current.original.equals(staged.original)) || current.mode !== staged.mode) throw new Error(`Localization file changed during translation: ${staged.realPath}. No staged changes were committed; rerun with the updated file.`);
267
+ }));
268
+ }
268
269
  async durableChanges() {
269
270
  return Promise.all([...this.files.values()].map(async (staged) => ({
270
271
  ...staged.mode === void 0 ? {} : { mode: staged.mode },
@@ -344,7 +345,10 @@ var StagedCatalogs = class {
344
345
  const mergeStagedState = catalog.mergeStagedState?.bind(catalog);
345
346
  return {
346
347
  createDocumentRef: (sourceRef, locale) => catalog.createDocumentRef(sourceRef, locale),
348
+ ...catalog.createScaffoldDocument === void 0 ? {} : { createScaffoldDocument: catalog.createScaffoldDocument.bind(catalog) },
347
349
  id: catalog.id,
350
+ ...catalog.messageFormats === void 0 ? {} : { messageFormats: catalog.messageFormats },
351
+ ...catalog.localizeSourceDocument === void 0 ? {} : { localizeSourceDocument: catalog.localizeSourceDocument.bind(catalog) },
348
352
  listDocumentRefs: (sourceLocale) => catalog.listDocumentRefs(sourceLocale),
349
353
  loadDocument: (ref) => this.loadStaged(catalog, ref),
350
354
  ...mergeStagedState === void 0 ? {} : { mergeStagedState },
@@ -385,11 +389,24 @@ var StagedCatalogs = class {
385
389
  skippedDocuments += 1;
386
390
  continue;
387
391
  }
388
- await adapter.writeDocument(await adapter.reconcileDocument({
392
+ const localizedSource = adapter.createScaffoldDocument !== void 0 || adapter.localizeSourceDocument === void 0 ? source : await adapter.localizeSourceDocument({
393
+ locale: options.locale,
394
+ source
395
+ });
396
+ const scaffold = adapter.createScaffoldDocument === void 0 ? await adapter.reconcileDocument({
389
397
  ref: targetRef,
390
- source,
398
+ source: localizedSource,
391
399
  target: null
392
- }));
400
+ }) : await adapter.createScaffoldDocument({
401
+ ref: targetRef,
402
+ source: localizedSource,
403
+ strategy
404
+ });
405
+ if (scaffold === null) {
406
+ skippedDocuments += 1;
407
+ continue;
408
+ }
409
+ await adapter.writeDocument(scaffold);
393
410
  createdDocuments += 1;
394
411
  }
395
412
  return {
@@ -425,6 +442,7 @@ async function runStagedCatalogTransaction(config, operation, shouldCommit = ()
425
442
  try {
426
443
  const result = await operation(stagedConfig);
427
444
  if (!shouldCommit(result)) return result;
445
+ await stagedCatalogs.verifyOriginals();
428
446
  const durableStore = durableStateStore(config.state);
429
447
  if (durableStore !== null) {
430
448
  const documents = await stagedCatalogs.durableChanges();
@@ -626,7 +644,7 @@ function printHelp() {
626
644
  console.log(`ai-translate
627
645
 
628
646
  Usage:
629
- ai-translate init [--integration <next-intl|i18next>] [--provider <openai|ai-sdk>] [--provider-package <@ai-sdk/...>] [--model <id>] [--preview] [--force]
647
+ ai-translate init [--integration <id>] [--provider <openai|ai-sdk>] [--provider-package <@ai-sdk/...>] [--model <id>] [--preview] [--force]
630
648
  ai-translate validate [--config <path>]
631
649
  ai-translate check [--config <path>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--include-path <json-pointer>] [--max-pending-translations <count>]
632
650
  ai-translate audit [--check] [--refresh] [--config <path>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--include-path <json-pointer>]
@@ -944,4 +962,4 @@ async function runCli(argv = process.argv.slice(2), cwd = process.cwd()) {
944
962
  //#endregion
945
963
  export { loadEnvFiles as a, loadConfig as i, runCli as n, findConfigPath as r, defineConfig$1 as t };
946
964
 
947
- //# sourceMappingURL=src-Cnnq284f.mjs.map
965
+ //# sourceMappingURL=src-Bb6vfpFm.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src-Bb6vfpFm.mjs","names":["fs","parseDotenv","nextIntegrations","fs","fs"],"sources":["../src/config.ts","../src/init.ts","../src/transaction.ts","../src/index.ts"],"sourcesContent":["import { existsSync, promises as fs } from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { config as loadDotenv, parse as parseDotenv } from \"dotenv\";\nimport { createJiti } from \"jiti\";\n\nimport { defineConfig } from \"@ai-translate/core\";\nimport type { AiTranslateConfig } from \"@ai-translate/core/types\";\n\nconst CONFIG_CANDIDATES = [\n \"ai-translate.config.ts\",\n \"ai-translate.config.mts\",\n \"ai-translate.config.js\",\n \"ai-translate.config.mjs\",\n] as const;\n\nfunction isAiTranslateConfig(value: unknown): value is AiTranslateConfig {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"catalogs\" in value &&\n \"provider\" in value &&\n \"sourceLocale\" in value &&\n \"state\" in value &&\n \"targetLocales\" in value\n );\n}\n\nexport function findConfigPath(cwd: string, explicitPath?: string): string {\n if (explicitPath) {\n return path.resolve(cwd, explicitPath);\n }\n\n for (const candidate of CONFIG_CANDIDATES) {\n const fullPath = path.join(cwd, candidate);\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n throw new Error(\n `Unable to find ai-translate config in ${cwd}. Expected one of: ${CONFIG_CANDIDATES.join(\", \")}`,\n );\n}\n\nexport async function loadEnvFiles(cwd: string): Promise<Record<string, string>> {\n const nodeEnv = process.env.NODE_ENV;\n const candidates = [\n \".env\",\n \".env.local\",\n nodeEnv ? `.env.${nodeEnv}` : undefined,\n nodeEnv ? `.env.${nodeEnv}.local` : undefined,\n ].filter((value): value is string => value !== undefined);\n\n const merged: Record<string, string> = {};\n for (const fileName of candidates) {\n const filePath = path.join(cwd, fileName);\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n Object.assign(merged, parseDotenv(raw));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n }\n\n loadDotenv({\n override: false,\n path: candidates.map((candidate) => path.join(cwd, candidate)),\n processEnv: process.env,\n });\n\n return merged;\n}\n\nexport async function loadConfig(\n cwd: string,\n explicitPath?: string,\n): Promise<{ config: AiTranslateConfig; configPath: string }> {\n const configPath = findConfigPath(cwd, explicitPath);\n const jiti = createJiti(import.meta.url, {\n interopDefault: true,\n moduleCache: false,\n });\n const loaded: unknown = await jiti.import(configPath);\n const resolved =\n typeof loaded === \"object\" && loaded !== null && \"default\" in loaded\n ? loaded.default ?? loaded\n : loaded;\n\n if (!isAiTranslateConfig(resolved)) {\n throw new Error(`Config file ${configPath} did not export an ai-translate config object.`);\n }\n\n return {\n config: defineConfig(resolved),\n configPath,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { appleIntegration } from \"@ai-translate/apple\";\nimport { detectProject, renderConfig, requiredConfigPackages } from \"@ai-translate/integrations\";\nimport type { DetectedSetup, Integration, ProviderChoice } from \"@ai-translate/integrations\";\nimport { builtinIntegrations as nextIntegrations } from \"@ai-translate/next\";\n\nconst CONFIG_FILENAME = \"ai-translate.config.ts\";\nconst DEFAULT_AI_SDK_PACKAGE = \"@ai-sdk/openai\";\n\n/** Platforms compose independent detectors; the runner has no platform dependencies. */\nexport const builtinInitIntegrations: readonly Integration[] = [...nextIntegrations, appleIntegration];\n\nexport interface InitOptions {\n /** Overwrites an existing config instead of refusing. */\n force?: boolean;\n /** Selects an integration when detection finds more than one. */\n integration?: string;\n /** Replaces the shipped integrations. A project that localizes something the\n * toolkit does not recognise can register its own detector rather than\n * writing the config by hand. */\n integrations?: readonly Integration[];\n /** Model id written into the generated config. */\n model?: string;\n /** Prints the config that would be written and touches nothing. */\n preview?: boolean;\n /** `openai` talks to OpenAI directly; `ai-sdk` routes through the AI SDK. */\n provider?: ProviderChoice;\n /** AI SDK vendor package, for example `@ai-sdk/anthropic`. */\n providerPackage?: string;\n}\n\nexport interface InitResult {\n configPath: string | null;\n lines: readonly string[];\n setup: DetectedSetup;\n}\n\nfunction describe(setup: DetectedSetup): string[] {\n return [\n `Detected ${setup.displayName}:`,\n ...setup.evidence.map((item) => ` - ${item.detail} (${item.source})`),\n ` - Source locale ${setup.plan.sourceLocale}, ${String(\n setup.plan.targetLocales.length,\n )} target locale(s): ${setup.plan.targetLocales.join(\", \")}`,\n ];\n}\n\nasync function missingPackages(\n cwd: string,\n plan: DetectedSetup[\"plan\"],\n options: InitOptions,\n): Promise<string[]> {\n const expected = requiredConfigPackages(plan, options);\n\n try {\n const raw = await fs.readFile(path.join(cwd, \"package.json\"), \"utf8\");\n const manifest = JSON.parse(raw) as Record<string, Record<string, string> | undefined>;\n const declared = new Set([\n ...Object.keys(manifest.dependencies ?? {}),\n ...Object.keys(manifest.devDependencies ?? {}),\n ]);\n return expected.filter((name) => !declared.has(name));\n } catch {\n return [...expected];\n }\n}\n\nfunction chooseSetup(\n setups: readonly DetectedSetup[],\n requested: string | undefined,\n): DetectedSetup {\n if (requested !== undefined) {\n const match = setups.find((setup) => setup.integrationId === requested);\n if (match === undefined) {\n throw new Error(\n `No ${requested} setup was detected. Detected: ${\n setups.map((setup) => setup.integrationId).join(\", \") || \"none\"\n }.`,\n );\n }\n return match;\n }\n\n const [best, ...rest] = setups;\n if (best === undefined) {\n throw new Error(\n \"No supported localization setup was found. ai-translate init recognises \" +\n \"next-intl and i18next, Apple String Catalogs, localized .strings tables, and Xcode or Apple Swift package projects. \" +\n \"For Expo, React Native, or Tauri apps with hardcoded text, first externalize strings into localization resources; \" +\n \"init does not extract text from application code. Run init from the project root, or write ai-translate.config.ts by hand.\",\n );\n }\n if (rest.length > 0 && rest[0]?.confidence === best.confidence) {\n // Two equally plausible setups is a genuine ambiguity, not something to\n // resolve by coin flip: writing the wrong one silently would point the\n // whole pipeline at the wrong catalog.\n throw new Error(\n `Found more than one localization setup (${setups\n .map((setup) => setup.integrationId)\n .join(\", \")}). Re-run with --integration <id> to choose.`,\n );\n }\n return best;\n}\n\n/**\n * Detects the project's localization setup and writes a config for it.\n *\n * Nothing else is touched. Installing packages, wiring scripts, and editing the\n * application configuration stay in the user's hands, so `init` on an unfamiliar repository\n * produces exactly one new file and a list of instructions.\n */\nexport async function runInit(cwd: string, options: InitOptions = {}): Promise<InitResult> {\n const setups = await detectProject(\n cwd,\n { integrations: options.integrations ?? builtinInitIntegrations },\n );\n const setup = chooseSetup(setups, options.integration);\n const contents = renderConfig(setup.plan, {\n ...(options.model === undefined ? {} : { model: options.model }),\n ...(options.provider === undefined ? {} : { provider: options.provider }),\n ...(options.providerPackage === undefined ? {} : { providerPackage: options.providerPackage }),\n });\n const configPath = path.join(cwd, CONFIG_FILENAME);\n const lines = describe(setup);\n\n for (const warning of setup.plan.warnings) {\n lines.push(` ! ${warning}`);\n }\n\n const others = setups.filter((candidate) => candidate !== setup);\n if (others.length > 0) {\n lines.push(\n `Also detected, not used: ${others.map((candidate) => candidate.displayName).join(\", \")}.`,\n );\n }\n\n if (options.preview === true) {\n lines.push(\"\", `Would write ${CONFIG_FILENAME}:`, \"\", contents);\n return { configPath: null, lines, setup };\n }\n\n const exists = await fs\n .access(configPath)\n .then(() => true)\n .catch(() => false);\n if (exists && options.force !== true) {\n throw new Error(`${CONFIG_FILENAME} already exists. Pass --force to overwrite it.`);\n }\n\n await fs.writeFile(configPath, contents, \"utf8\");\n lines.push(\"\", `Wrote ${CONFIG_FILENAME}.`, \"\", \"Next steps:\");\n\n const install = await missingPackages(cwd, setup.plan, options);\n let step = 1;\n if (install.length > 0) {\n lines.push(` ${String(step++)}. Install: ${install.join(\" \")}`);\n }\n const apiKeyVariable =\n options.provider === \"ai-sdk\"\n ? `the API key your ${options.providerPackage ?? DEFAULT_AI_SDK_PACKAGE} provider reads`\n : \"OPENAI_API_KEY\";\n lines.push(\n ` ${String(step++)}. Set ${apiKeyVariable}, in your shell or in .env.local.`,\n ` ${String(step++)}. Review the model and locale list in ${CONFIG_FILENAME}.`,\n ` ${String(step++)}. Run \"ai-translate validate\" to confirm the config loads.`,\n ` ${String(step++)}. Run \"ai-translate check\" to see what a sync would do.`,\n ` ${String(step)}. Run \"ai-translate sync\" to translate.`,\n );\n\n return { configPath, lines, setup };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nimport type {\n AiTranslateConfig,\n CatalogAdapter,\n DocumentRef,\n Entry,\n LoadedDocument,\n ScaffoldLocaleOptions,\n ScaffoldLocaleResult,\n SyncStateLoadScope,\n SyncStateSnapshot,\n SyncStateStore,\n} from \"@ai-translate/core/types\";\nimport { supportsScopedSave } from \"@ai-translate/core/types\";\nimport type {\n DurableDocumentChange,\n} from \"@ai-translate/fs-json\";\n\nconst DURABLE_TRANSACTION_STATE_STORE = Symbol.for(\n \"@ai-translate/fs-json/durable-transaction-state-store\",\n);\n\nfunction cloneState(state: SyncStateSnapshot): SyncStateSnapshot {\n return structuredClone(state);\n}\n\nfunction cloneEntry(entry: Entry): Entry {\n return {\n ...entry,\n address: entry.address.map((segment) => ({ ...segment })),\n ...(entry.context === undefined ? {} : { context: structuredClone(entry.context) }),\n ...(entry.meta === undefined ? {} : { meta: { ...entry.meta } }),\n ...(entry.tokens === undefined ? {} : { tokens: entry.tokens.map((token) => ({ ...token })) }),\n };\n}\n\n/** Adapter state may contain parser-owned class instances, so retain it while\n * isolating the mutable translation entries. Staged writes are subsequently\n * serialized and reloaded by the real adapter to obtain isolated live state. */\nfunction cloneDocument(document: LoadedDocument): LoadedDocument {\n return {\n entries: document.entries.map(cloneEntry),\n ...(document.reconciliation === undefined\n ? {}\n : {\n reconciliation: {\n ...(document.reconciliation.previousPointers === undefined\n ? {}\n : { previousPointers: { ...document.reconciliation.previousPointers } }),\n ...(document.reconciliation.retiredStateKeys === undefined\n ? {}\n : { retiredStateKeys: [...document.reconciliation.retiredStateKeys] }),\n },\n }),\n ref: { ...document.ref },\n state: document.state,\n ...(document.structureDigest === undefined\n ? {}\n : { structureDigest: document.structureDigest }),\n };\n}\n\nfunction restoreDocumentRef(document: LoadedDocument, ref: DocumentRef): LoadedDocument {\n return cloneDocument({ ...document, ref: { ...ref } });\n}\n\nfunction documentKey(ref: DocumentRef): string {\n return [ref.catalogId, ref.format, ref.locale, ref.path, ref.unitId].join(\"\\u0000\");\n}\n\nclass StagedStateStore implements SyncStateStore {\n private dirty = false;\n private snapshot: SyncStateSnapshot;\n\n constructor(initial: SyncStateSnapshot) {\n this.snapshot = cloneState(initial);\n }\n\n hasChanges(): boolean {\n return this.dirty;\n }\n\n load(): Promise<SyncStateSnapshot> {\n return Promise.resolve(cloneState(this.snapshot));\n }\n\n save(state: SyncStateSnapshot): Promise<void> {\n this.snapshot = cloneState(state);\n this.dirty = true;\n return Promise.resolve();\n }\n\n stagedSnapshot(): SyncStateSnapshot {\n return cloneState(this.snapshot);\n }\n\n withLock<T>(operation: () => Promise<T>): Promise<T> {\n return operation();\n }\n}\n\ninterface StagedFile {\n mode: number | undefined;\n original: Buffer | null;\n realPath: string;\n tempPath: string;\n}\n\nasync function readOriginal(filePath: string): Promise<{\n mode: number | undefined;\n original: Buffer | null;\n}> {\n try {\n const [original, stats] = await Promise.all([fs.readFile(filePath), fs.stat(filePath)]);\n return { mode: stats.mode, original };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { mode: undefined, original: null };\n }\n throw error;\n }\n}\n\nasync function writeFileAtomic(filePath: string, contents: Buffer, mode?: number): Promise<void> {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n const temporaryPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.ai-translate-${randomUUID()}`,\n );\n try {\n await fs.writeFile(temporaryPath, contents);\n if (mode !== undefined) {\n await fs.chmod(temporaryPath, mode);\n }\n await fs.rename(temporaryPath, filePath);\n } finally {\n await fs.rm(temporaryPath, { force: true });\n }\n}\n\nclass StagedCatalogs {\n private readonly files = new Map<string, StagedFile>();\n private readonly pendingRefs = new Map<string, { catalog: CatalogAdapter; ref: DocumentRef }>();\n private tempRoot: string | undefined;\n\n constructor(\n private readonly catalogs: readonly CatalogAdapter[],\n private readonly sourceLocale: string,\n ) {}\n\n adapters(): readonly CatalogAdapter[] {\n return this.catalogs.map((catalog) => this.createAdapter(catalog));\n }\n\n async cleanup(): Promise<void> {\n if (this.tempRoot !== undefined) {\n await fs.rm(this.tempRoot, { force: true, recursive: true });\n }\n }\n\n async promote(): Promise<void> {\n for (const staged of this.files.values()) {\n await writeFileAtomic(staged.realPath, await fs.readFile(staged.tempPath), staged.mode);\n }\n }\n\n async verifyOriginals(): Promise<void> {\n await Promise.all([...this.files.values()].map(async (staged) => {\n const current = await readOriginal(staged.realPath);\n const sameBytes = current.original === null\n ? staged.original === null\n : staged.original !== null && current.original.equals(staged.original);\n if (!sameBytes || current.mode !== staged.mode) {\n throw new Error(`Localization file changed during translation: ${staged.realPath}. No staged changes were committed; rerun with the updated file.`);\n }\n }));\n }\n\n async durableChanges(): Promise<readonly DurableDocumentChange[]> {\n return Promise.all(\n [...this.files.values()].map(async (staged) => ({\n ...(staged.mode === undefined ? {} : { mode: staged.mode }),\n next: await fs.readFile(staged.tempPath),\n original: staged.original,\n path: staged.realPath,\n })),\n );\n }\n\n async rollback(): Promise<void> {\n const failures: unknown[] = [];\n for (const staged of this.files.values()) {\n try {\n if (staged.original === null) {\n await fs.rm(staged.realPath, { force: true });\n } else {\n await writeFileAtomic(staged.realPath, staged.original, staged.mode);\n }\n } catch (error) {\n failures.push(error);\n }\n }\n if (failures.length > 0) {\n throw new AggregateError(failures, \"Failed to restore localized documents after commit.\");\n }\n }\n\n private async stageFile(realPath: string): Promise<StagedFile> {\n const existing = this.files.get(realPath);\n if (existing) {\n return existing;\n }\n this.tempRoot ??= await fs.mkdtemp(path.join(os.tmpdir(), \"ai-translate-stage-\"));\n const { mode, original } = await readOriginal(realPath);\n const tempPath = path.join(\n this.tempRoot,\n `${String(this.files.size)}${path.extname(realPath) || \".document\"}`,\n );\n if (original !== null) {\n await fs.writeFile(tempPath, original);\n }\n const staged = { mode, original, realPath, tempPath };\n this.files.set(realPath, staged);\n return staged;\n }\n\n private async loadStaged(\n catalog: CatalogAdapter,\n ref: DocumentRef,\n ): Promise<LoadedDocument | null> {\n const staged = this.files.get(ref.path);\n if (!staged) {\n const document = await catalog.loadDocument(ref);\n return document === null ? null : cloneDocument(document);\n }\n const tempRef = { ...ref, path: staged.tempPath };\n const document = await catalog.loadDocument(tempRef);\n return document === null ? null : restoreDocumentRef(document, ref);\n }\n\n private async writeStaged(catalog: CatalogAdapter, document: LoadedDocument): Promise<void> {\n const staged = await this.stageFile(document.ref.path);\n const tempRef = { ...document.ref, path: staged.tempPath };\n const stagedDocument = await catalog.loadDocument(tempRef);\n await catalog.writeDocument({\n ...cloneDocument(document),\n ref: tempRef,\n // The reconciled document is authoritative: it carries the source shape,\n // so keys dropped from the source do not survive in the target. Formats\n // that pack several logical documents into one file merge that shape\n // into the staged file themselves so sibling writes are not lost.\n state:\n stagedDocument === null || catalog.mergeStagedState === undefined\n ? document.state\n : catalog.mergeStagedState({ document, staged: stagedDocument }),\n });\n const persisted = await catalog.loadDocument(tempRef);\n if (persisted === null) {\n throw new Error(\n `Catalog \"${catalog.id}\" did not persist staged document ${document.ref.path}.`,\n );\n }\n this.pendingRefs.set(documentKey(document.ref), { catalog, ref: { ...document.ref } });\n\n // A bundle catalog can expose several logical documents backed by one file.\n // Re-read every staged ref for the path so later repair rounds see the\n // aggregate serialized state, not a pre-write per-unit snapshot.\n for (const pending of this.pendingRefs.values()) {\n if (pending.ref.path === document.ref.path) {\n const pendingTempRef = { ...pending.ref, path: staged.tempPath };\n if ((await pending.catalog.loadDocument(pendingTempRef)) === null) {\n throw new Error(\n `Catalog \"${pending.catalog.id}\" could not reload staged document ${pending.ref.path}.`,\n );\n }\n }\n }\n }\n\n private createAdapter(catalog: CatalogAdapter): CatalogAdapter {\n const mergeStagedState = catalog.mergeStagedState?.bind(catalog);\n return {\n createDocumentRef: (sourceRef, locale) => catalog.createDocumentRef(sourceRef, locale),\n ...(catalog.createScaffoldDocument === undefined\n ? {}\n : { createScaffoldDocument: catalog.createScaffoldDocument.bind(catalog) }),\n id: catalog.id,\n ...(catalog.messageFormats === undefined ? {} : { messageFormats: catalog.messageFormats }),\n ...(catalog.localizeSourceDocument === undefined\n ? {}\n : { localizeSourceDocument: catalog.localizeSourceDocument.bind(catalog) }),\n listDocumentRefs: (sourceLocale) => catalog.listDocumentRefs(sourceLocale),\n loadDocument: (ref) => this.loadStaged(catalog, ref),\n ...(mergeStagedState === undefined ? {} : { mergeStagedState }),\n reconcileDocument: async (args) => {\n const document = await catalog.reconcileDocument({\n ...(args.history === undefined\n ? {}\n : { history: args.history.map((entry) => structuredClone(entry)) }),\n ref: { ...args.ref },\n source: cloneDocument(args.source),\n target: args.target === null ? null : cloneDocument(args.target),\n });\n return cloneDocument(document);\n },\n ...(catalog.scaffoldLocale === undefined\n ? {}\n : {\n scaffoldLocale: (options: ScaffoldLocaleOptions) =>\n this.scaffoldCatalog(catalog, options),\n }),\n writeDocument: (document) => this.writeStaged(catalog, document),\n };\n }\n\n private async scaffoldCatalog(\n catalog: CatalogAdapter,\n options: ScaffoldLocaleOptions,\n ): Promise<ScaffoldLocaleResult> {\n const strategy = options.strategy ?? \"copy-source\";\n const fromLocale =\n strategy === \"copy-source\" ? this.sourceLocale : (options.fromLocale ?? this.sourceLocale);\n const refs = await catalog.listDocumentRefs(fromLocale);\n if (strategy === \"empty\") {\n return {\n catalogId: catalog.id,\n createdDocuments: 0,\n locale: options.locale,\n skippedDocuments: refs.length,\n strategy,\n };\n }\n\n let createdDocuments = 0;\n let skippedDocuments = 0;\n const adapter = this.createAdapter(catalog);\n for (const sourceRef of refs) {\n const targetRef = adapter.createDocumentRef(sourceRef, options.locale);\n if ((await adapter.loadDocument(targetRef)) !== null) {\n skippedDocuments += 1;\n continue;\n }\n const source = await adapter.loadDocument(sourceRef);\n if (source === null) {\n skippedDocuments += 1;\n continue;\n }\n const localizedSource = adapter.createScaffoldDocument !== undefined || adapter.localizeSourceDocument === undefined\n ? source\n : await adapter.localizeSourceDocument({ locale: options.locale, source });\n const scaffold = adapter.createScaffoldDocument === undefined\n ? await adapter.reconcileDocument({ ref: targetRef, source: localizedSource, target: null })\n : await adapter.createScaffoldDocument({ ref: targetRef, source: localizedSource, strategy });\n if (scaffold === null) {\n skippedDocuments += 1;\n continue;\n }\n await adapter.writeDocument(scaffold);\n createdDocuments += 1;\n }\n\n return {\n catalogId: catalog.id,\n createdDocuments,\n locale: options.locale,\n skippedDocuments,\n strategy,\n };\n }\n}\n\nfunction commitFailure(commitError: unknown, rollbackErrors: readonly unknown[]): Error {\n return rollbackErrors.length === 0\n ? commitError instanceof Error\n ? commitError\n : new Error(String(commitError))\n : new AggregateError(\n [commitError, ...rollbackErrors],\n \"Translation commit failed and could not be completely rolled back.\",\n );\n}\n\ninterface DurableCommitCoordinator {\n commit(transaction: {\n documents: readonly DurableDocumentChange[];\n initialState: SyncStateSnapshot;\n nextState: SyncStateSnapshot;\n }): Promise<void>;\n}\n\nfunction durableStateStore(state: SyncStateStore): DurableCommitCoordinator | null {\n if (typeof state === \"object\" && state !== null) {\n const candidate = (state as unknown as Record<PropertyKey, unknown>)[\n DURABLE_TRANSACTION_STATE_STORE\n ];\n if (\n typeof candidate === \"object\" &&\n candidate !== null &&\n \"commit\" in candidate &&\n typeof candidate.commit === \"function\"\n ) {\n return candidate as DurableCommitCoordinator;\n }\n }\n return null;\n}\n\nexport async function runStagedCatalogTransaction<T>(\n config: AiTranslateConfig,\n operation: (stagedConfig: AiTranslateConfig) => Promise<T>,\n shouldCommit: (result: T) => boolean = () => true,\n scope?: SyncStateLoadScope,\n): Promise<T> {\n /*\n * Staging copies the snapshot several times between here and the commit, so\n * loading locales the run cannot touch is the dominant cost of a narrow sync.\n * The scope is only honoured by stores that merge on save; everywhere else the\n * snapshot still has to describe the whole corpus, because omission means\n * deletion.\n */\n const saveScope = supportsScopedSave(config.state) ? scope : undefined;\n\n return config.state.withLock(async () => {\n const initialState = await config.state.load(saveScope);\n const stagedState = new StagedStateStore(initialState);\n const stagedCatalogs = new StagedCatalogs(config.catalogs, config.sourceLocale);\n const stagedConfig: AiTranslateConfig = {\n ...config,\n catalogs: stagedCatalogs.adapters(),\n state: stagedState,\n };\n try {\n const result = await operation(stagedConfig);\n if (!shouldCommit(result)) {\n return result;\n }\n\n // A shared resource can contain source strings and unrelated locales.\n // Check every file before either commit path starts. A conflict must not\n // enter rollback: restoring the old snapshot would erase the new edits.\n await stagedCatalogs.verifyOriginals();\n const durableStore = durableStateStore(config.state);\n if (durableStore !== null) {\n const documents = await stagedCatalogs.durableChanges();\n if (documents.length > 0 || stagedState.hasChanges()) {\n await durableStore.commit({\n documents,\n initialState: cloneState(initialState),\n nextState: stagedState.stagedSnapshot(),\n ...(saveScope === undefined ? {} : { scope: saveScope }),\n });\n }\n } else {\n let stateSaveAttempted = false;\n try {\n await stagedCatalogs.promote();\n if (stagedState.hasChanges()) {\n stateSaveAttempted = true;\n await config.state.save(stagedState.stagedSnapshot(), saveScope);\n }\n } catch (error) {\n const rollbackErrors: unknown[] = [];\n try {\n await stagedCatalogs.rollback();\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n if (stateSaveAttempted) {\n try {\n await config.state.save(cloneState(initialState), saveScope);\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n }\n throw commitFailure(error, rollbackErrors);\n }\n }\n return result;\n } finally {\n await stagedCatalogs.cleanup();\n }\n });\n}\n","import {\n auditCatalogs,\n resolveStateScope,\n syncCatalogs,\n usesGeneratorSelfCheck,\n validateCatalogs,\n withTranslationIssueCache,\n} from \"@ai-translate/core\";\nimport type {\n AiTranslateConfig,\n CatalogScaffoldStrategy,\n SemanticAuditResult,\n SyncCatalogsOptions,\n SyncResult,\n SyncStateSnapshot,\n ValidationResult,\n} from \"@ai-translate/core/types\";\nimport { adoptExistingTranslations } from \"@ai-translate/fs-json\";\nimport type { IdenticalToSourcePolicy } from \"@ai-translate/fs-json\";\nimport type { ProviderChoice } from \"@ai-translate/next\";\n\nimport { loadConfig, loadEnvFiles } from \"./config\";\nimport { runInit } from \"./init\";\nimport { runStagedCatalogTransaction } from \"./transaction\";\n\nexport { defineConfig } from \"@ai-translate/core\";\nexport { findConfigPath, loadConfig, loadEnvFiles } from \"./config\";\n\ninterface CommandOptions {\n auditCheck?: boolean;\n catalogIds?: string[];\n config?: string;\n dryRun?: boolean;\n force?: boolean;\n forceRetranslate?: boolean;\n forceRetranslatePaths?: string[];\n includePaths?: string[];\n from?: string;\n identicalToSource?: IdenticalToSourcePolicy;\n locales?: string[];\n integration?: string;\n maxPendingTranslations?: number;\n model?: string;\n preview?: boolean;\n provider?: string;\n providerPackage?: string;\n refresh?: boolean;\n strategy?: CatalogScaffoldStrategy;\n unitIds?: string[];\n}\n\ninterface ParsedCommand {\n command?: string;\n options: CommandOptions;\n positionals: string[];\n}\n\nfunction requireOptionValue(optionName: string, value: string | undefined): string {\n if (value === undefined) {\n throw new Error(`Option \"--${optionName}\" requires a value.`);\n }\n\n return value;\n}\n\nfunction requireProviderChoice(value: string): ProviderChoice {\n if (value !== \"ai-sdk\" && value !== \"openai\") {\n throw new Error(`Option \"--provider\" accepts \"openai\" or \"ai-sdk\", not \"${value}\".`);\n }\n\n return value;\n}\n\nfunction requireIdenticalToSourcePolicy(value: string): IdenticalToSourcePolicy {\n if (value !== \"adopt\" && value !== \"skip\") {\n throw new Error(\n `Option \"--identical-to-source\" accepts \"adopt\" or \"skip\", not \"${value}\".`,\n );\n }\n\n return value;\n}\n\nfunction requireNonNegativeIntegerOption(optionName: string, value: string | undefined): number {\n const rawValue = requireOptionValue(optionName, value);\n const parsedValue = Number(rawValue);\n if (!Number.isSafeInteger(parsedValue) || parsedValue < 0) {\n throw new Error(`Option \"--${optionName}\" requires a non-negative integer.`);\n }\n return parsedValue;\n}\n\nasync function validateConfig(\n config: AiTranslateConfig,\n configPath: string,\n options: SyncCatalogsOptions,\n): Promise<ValidationResult> {\n const result = await validateCatalogs(config, options);\n return {\n ...result,\n configPath,\n };\n}\n\nconst DEFAULT_SEMANTIC_REPAIR_ROUNDS = 0;\n\ninterface SemanticAuditConvergenceResult {\n audit: SemanticAuditResult | undefined;\n repairRounds: number;\n sync: SyncResult;\n}\n\nfunction printSyncSummary(\n result: SyncResult,\n semanticAudit?: SemanticAuditResult,\n semanticRepairRounds = 0,\n): void {\n const pendingTranslationReasons = summarizePendingTranslationReasons(result);\n const failedTranslationIssues = summarizeFailedTranslationIssues(result);\n console.log(\n JSON.stringify(\n {\n dryRun: result.dryRun,\n metrics: result.metrics,\n ...(result.dryRun && Object.keys(pendingTranslationReasons).length > 0\n ? { pendingTranslationReasons }\n : {}),\n ...(semanticAudit === undefined ? {} : { semanticAudit, semanticRepairRounds }),\n ...(failedTranslationIssues === undefined ? {} : { failedTranslationIssues }),\n },\n null,\n 2,\n ),\n );\n}\n\nfunction summarizeFailedTranslationIssues(result: SyncResult):\n | {\n counts: Record<string, number>;\n examples: readonly {\n catalogId: string;\n code: string;\n locale: string;\n message: string;\n path: string;\n unitId: string;\n }[];\n }\n | undefined {\n if (result.metrics.failedEntries === 0) {\n return undefined;\n }\n const errors = result.documents.flatMap((document) =>\n document.issues\n .filter((issue) => issue.severity === \"error\")\n .map((issue) => ({\n catalogId: document.catalogId,\n code: issue.code,\n locale: document.locale,\n message: issue.message,\n path: document.path,\n unitId: document.unitId,\n })),\n );\n const counts: Record<string, number> = {};\n for (const issue of errors) {\n counts[issue.code] = (counts[issue.code] ?? 0) + 1;\n }\n return {\n counts: Object.fromEntries(\n Object.entries(counts).toSorted(\n ([leftCode, leftCount], [rightCode, rightCount]) =>\n rightCount - leftCount || leftCode.localeCompare(rightCode),\n ),\n ),\n examples: errors.slice(0, 25),\n };\n}\n\nfunction summarizePendingTranslationReasons(result: SyncResult): Record<string, number> {\n const summary: Record<string, number> = {};\n for (const document of result.documents) {\n for (const [reason, count] of Object.entries(document.pendingTranslationReasons ?? {})) {\n summary[reason] = (summary[reason] ?? 0) + count;\n }\n }\n return Object.fromEntries(\n Object.entries(summary).toSorted(\n ([leftReason, leftCount], [rightReason, rightCount]) =>\n rightCount - leftCount || leftReason.localeCompare(rightReason),\n ),\n );\n}\n\nfunction dryRunBudgetError(config: AiTranslateConfig, result: SyncResult): string | undefined {\n if (!result.dryRun || config.validation?.dryRunBudget === undefined) {\n return undefined;\n }\n const budget = config.validation.dryRunBudget;\n if (\n budget.maxPendingTranslations !== undefined &&\n result.metrics.translatedEntries > budget.maxPendingTranslations\n ) {\n return (\n `Translation dry-run planned ${String(\n result.metrics.translatedEntries,\n )} provider translations, ` +\n `exceeding the configured budget of ${String(budget.maxPendingTranslations)}.`\n );\n }\n const reasons = summarizePendingTranslationReasons(result);\n const forbidden = (budget.forbiddenPendingTranslationReasons ?? []).filter(\n (reason) => (reasons[reason] ?? 0) > 0,\n );\n return forbidden.length === 0\n ? undefined\n : `Translation dry-run included forbidden selection reasons: ${forbidden\n .map((reason) => `${reason} (${String(reasons[reason] ?? 0)})`)\n .join(\", \")}.`;\n}\n\nfunction assertDryRunBudget(config: AiTranslateConfig, result: SyncResult): void {\n const error = dryRunBudgetError(config, result);\n if (error !== undefined) {\n throw new Error(error);\n }\n}\n\nasync function convergeSemanticAudits(\n config: AiTranslateConfig,\n options: SyncCatalogsOptions,\n): Promise<SemanticAuditConvergenceResult> {\n let sync = await syncCatalogs(config, options);\n if (\n options.dryRun === true ||\n sync.metrics.failedEntries > 0 ||\n (config.semanticAudits?.length ?? 0) === 0 ||\n usesGeneratorSelfCheck(config)\n ) {\n return { audit: undefined, repairRounds: 0, sync };\n }\n\n let audit = await auditCatalogs(config, options);\n let repairRounds = 0;\n const maxSemanticRepairRounds =\n config.validation?.semanticRepairAttempts ?? DEFAULT_SEMANTIC_REPAIR_ROUNDS;\n const repairOptions = { ...options };\n delete repairOptions.forceRetranslate;\n delete repairOptions.forceRetranslatePaths;\n while (audit.retranslate > 0 && repairRounds < maxSemanticRepairRounds) {\n repairRounds += 1;\n sync = await syncCatalogs(config, repairOptions);\n if (sync.metrics.failedEntries > 0) {\n break;\n }\n audit = await auditCatalogs(config, options);\n }\n\n return { audit, repairRounds, sync };\n}\n\nasync function syncWithSemanticAuditConvergence(\n config: AiTranslateConfig,\n options: SyncCatalogsOptions,\n): Promise<SemanticAuditConvergenceResult> {\n if (options.dryRun === true) {\n return convergeSemanticAudits(config, options);\n }\n return runStagedCatalogTransaction(\n config,\n (stagedConfig) => convergeSemanticAudits(stagedConfig, options),\n (result) => semanticAuditConvergenceError(result) === undefined,\n resolveStateScope(config, options),\n );\n}\n\nfunction semanticAuditConvergenceError(result: SemanticAuditConvergenceResult): string | undefined {\n if (result.sync.metrics.failedEntries > 0) {\n return \"Sync completed with failed translation entries.\";\n }\n if ((result.audit?.unresolved ?? 0) > 0) {\n return \"Sync completed with unresolved semantic audits. Review or refresh the audit findings.\";\n }\n if ((result.audit?.retranslate ?? 0) > 0) {\n return `Semantic audit rejected translations after ${String(\n result.repairRounds,\n )} configured repair round(s).`;\n }\n if (result.audit?.issues.some((issue) => issue.severity === \"error\")) {\n return \"Semantic audit completed with unresolved or unsafe translations.\";\n }\n return undefined;\n}\n\nfunction assertSemanticAuditConvergence(result: SemanticAuditConvergenceResult): void {\n const error = semanticAuditConvergenceError(result);\n if (error !== undefined) {\n throw new Error(error);\n }\n}\n\nfunction buildSyncOptions(options: CommandOptions): SyncCatalogsOptions {\n const syncOptions: SyncCatalogsOptions = {};\n if (options.catalogIds && options.catalogIds.length > 0) {\n syncOptions.catalogIds = options.catalogIds;\n }\n\n if (options.dryRun !== undefined) {\n syncOptions.dryRun = options.dryRun;\n }\n\n if (options.forceRetranslate !== undefined) {\n syncOptions.forceRetranslate = options.forceRetranslate;\n }\n\n if (options.forceRetranslatePaths && options.forceRetranslatePaths.length > 0) {\n syncOptions.forceRetranslate = true;\n syncOptions.forceRetranslatePaths = options.forceRetranslatePaths;\n }\n\n if (options.includePaths && options.includePaths.length > 0) {\n syncOptions.includePaths = options.includePaths;\n }\n\n if (options.locales && options.locales.length > 0) {\n syncOptions.locales = options.locales;\n }\n\n if (options.maxPendingTranslations !== undefined) {\n syncOptions.maxPendingTranslations = options.maxPendingTranslations;\n }\n\n if (options.unitIds && options.unitIds.length > 0) {\n syncOptions.unitIds = options.unitIds;\n }\n\n return syncOptions;\n}\n\nfunction projectStateLocales(\n state: SyncStateSnapshot,\n locales: readonly string[] | undefined,\n): SyncStateSnapshot {\n if (locales === undefined || locales.length === 0) {\n return state;\n }\n const included = new Set(locales);\n return {\n entries: Object.fromEntries(\n Object.entries(state.entries).filter(([, entry]) => included.has(entry.locale)),\n ),\n version: state.version,\n };\n}\n\nfunction hasStoredSemanticAudits(state: SyncStateSnapshot): boolean {\n return Object.values(state.entries).some(\n (entry) => Object.keys(entry.validationAudits ?? {}).length > 0,\n );\n}\n\nconst EMPTY_SEMANTIC_AUDIT = {\n accepted: 0,\n audited: 0,\n cached: 0,\n checked: 0,\n issues: [],\n retranslate: 0,\n unresolved: 0,\n} as const;\n\nasync function scaffoldLocale(\n config: AiTranslateConfig,\n locale: string,\n options: {\n fromLocale?: string;\n strategy?: CatalogScaffoldStrategy;\n } = {},\n) {\n return Promise.all(\n config.catalogs.map(async (catalog) => {\n if (!catalog.scaffoldLocale) {\n return null;\n }\n\n return catalog.scaffoldLocale({\n ...(options.fromLocale === undefined ? {} : { fromLocale: options.fromLocale }),\n locale,\n ...(options.strategy === undefined ? {} : { strategy: options.strategy }),\n });\n }),\n );\n}\n\nfunction printHelp(): void {\n console.log(`ai-translate\n\nUsage:\n ai-translate init [--integration <id>] [--provider <openai|ai-sdk>] [--provider-package <@ai-sdk/...>] [--model <id>] [--preview] [--force]\n ai-translate validate [--config <path>]\n ai-translate check [--config <path>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--include-path <json-pointer>] [--max-pending-translations <count>]\n ai-translate audit [--check] [--refresh] [--config <path>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--include-path <json-pointer>]\n ai-translate sync [--config <path>] [--dry-run] [--force-retranslate] [--force-retranslate-path <json-pointer>] [--include-path <json-pointer>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--max-pending-translations <count>]\n ai-translate new-locale <locale> [--from <locale>] [--strategy <strategy>] [--config <path>]\n ai-translate scaffold-locale <locale> --from <locale> [--strategy <strategy>] [--config <path>]\n ai-translate adopt [--identical-to-source <adopt|skip>] [--dry-run] [--config <path>]\n ai-translate --help\n ai-translate --version`);\n}\n\nfunction parseCommand(argv: readonly string[]): ParsedCommand {\n const options: CommandOptions = {};\n const positionals: string[] = [];\n let command: string | undefined;\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (arg === undefined) {\n continue;\n }\n\n if (arg === \"--help\" || arg === \"-h\") {\n return {\n command: \"help\",\n options,\n positionals,\n };\n }\n\n if (arg === \"--version\" || arg === \"-v\") {\n return {\n command: \"version\",\n options,\n positionals,\n };\n }\n\n if (arg.startsWith(\"--\")) {\n const [flag = \"\", inlineValue] = arg.slice(2).split(\"=\", 2);\n if (flag.length === 0) {\n throw new Error(\"Encountered an empty option flag.\");\n }\n\n const nextValue = inlineValue ?? argv[index + 1];\n switch (flag) {\n case \"check\":\n options.auditCheck = true;\n break;\n case \"config\":\n options.config = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"catalog\":\n (options.catalogIds ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"dry-run\":\n options.dryRun = true;\n break;\n case \"force\":\n options.force = true;\n break;\n case \"force-retranslate\":\n options.forceRetranslate = true;\n break;\n case \"force-retranslate-path\":\n (options.forceRetranslatePaths ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"from\":\n options.from = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"include-path\":\n (options.includePaths ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"integration\":\n options.integration = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"locale\":\n (options.locales ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"model\":\n options.model = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"preview\":\n options.preview = true;\n break;\n case \"provider\":\n options.provider = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"provider-package\":\n options.providerPackage = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"max-pending-translations\":\n options.maxPendingTranslations = requireNonNegativeIntegerOption(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"identical-to-source\":\n options.identicalToSource = requireIdenticalToSourcePolicy(\n requireOptionValue(flag, nextValue),\n );\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"refresh\":\n options.refresh = true;\n break;\n case \"strategy\": {\n const strategy = requireOptionValue(flag, nextValue) as CatalogScaffoldStrategy;\n options.strategy = strategy;\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n }\n case \"unit\":\n (options.unitIds ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n default:\n throw new Error(`Unknown option \"--${flag}\".`);\n }\n\n continue;\n }\n\n if (!command) {\n command = arg;\n continue;\n }\n\n positionals.push(arg);\n }\n\n const parsedCommand: ParsedCommand = {\n options,\n positionals,\n };\n if (command !== undefined) {\n parsedCommand.command = command;\n }\n\n return parsedCommand;\n}\n\nexport async function runCli(\n argv: readonly string[] = process.argv.slice(2),\n cwd: string = process.cwd(),\n): Promise<number> {\n try {\n const parsed = parseCommand(argv);\n if (!parsed.command || parsed.command === \"help\") {\n printHelp();\n return 0;\n }\n\n if (parsed.command === \"version\") {\n console.log(\"0.0.0\");\n return 0;\n }\n\n switch (parsed.command) {\n case \"init\": {\n // No loadConfig and no loadEnvFiles: init runs before either exists.\n const result = await runInit(cwd, {\n force: parsed.options.force === true,\n ...(parsed.options.integration === undefined\n ? {}\n : { integration: parsed.options.integration }),\n ...(parsed.options.model === undefined ? {} : { model: parsed.options.model }),\n preview: parsed.options.preview === true || parsed.options.dryRun === true,\n ...(parsed.options.provider === undefined\n ? {}\n : { provider: requireProviderChoice(parsed.options.provider) }),\n ...(parsed.options.providerPackage === undefined\n ? {}\n : { providerPackage: parsed.options.providerPackage }),\n });\n console.log(result.lines.join(\"\\n\"));\n return 0;\n }\n case \"validate\": {\n await loadEnvFiles(cwd);\n const { config, configPath } = await loadConfig(cwd, parsed.options.config);\n const summary = await validateConfig(config, configPath, buildSyncOptions(parsed.options));\n console.log(JSON.stringify(summary, null, 2));\n if (summary.issues.some((issue) => issue.severity === \"error\")) {\n throw new Error(\"Validation failed.\");\n }\n return 0;\n }\n case \"check\": {\n await loadEnvFiles(cwd);\n const { config, configPath } = await loadConfig(cwd, parsed.options.config);\n const checkOptions: SyncCatalogsOptions = {\n ...buildSyncOptions(parsed.options),\n ...(process.env.AI_TRANSLATE_CHECK_SNAPSHOT_LOCK === \"1\"\n ? { assumeStateLock: true }\n : {}),\n };\n // Ask the store to materialise only the locales under check, then keep\n // the projection: a store is free to ignore the scope and return a\n // superset, and check must narrow regardless of which store is wired up.\n const stateSnapshot = projectStateLocales(\n await config.state.load(\n checkOptions.locales === undefined ? undefined : { locales: checkOptions.locales },\n ),\n checkOptions.locales,\n );\n const checkConfig: AiTranslateConfig = {\n ...config,\n state: {\n load: () => Promise.resolve(stateSnapshot),\n save: () =>\n Promise.reject(new Error(\"Translation check cannot persist translation state.\")),\n withLock: (operation) => config.state.withLock(operation),\n },\n };\n const needsSemanticAudit =\n (checkConfig.semanticAudits?.length ?? 0) > 0 || hasStoredSemanticAudits(stateSnapshot);\n const { auditResult, dryRunResult, validationResult } = await withTranslationIssueCache(\n async () => {\n const checkedValidation = await validateConfig(checkConfig, configPath, {\n ...checkOptions,\n acceptedProvenanceFastPath: true,\n });\n const checkedDryRun = await syncCatalogs(checkConfig, {\n ...checkOptions,\n dryRun: true,\n });\n const checkedAudit = needsSemanticAudit\n ? await auditCatalogs(checkConfig, {\n ...checkOptions,\n checkOnly: true,\n })\n : EMPTY_SEMANTIC_AUDIT;\n return {\n auditResult: checkedAudit,\n dryRunResult: checkedDryRun,\n validationResult: checkedValidation,\n };\n },\n );\n const hasValidationErrors = validationResult.issues.some(\n (issue) => issue.severity === \"error\",\n );\n const hasPendingSync =\n dryRunResult.metrics.changedDocuments > 0 ||\n dryRunResult.metrics.failedEntries > 0 ||\n dryRunResult.metrics.staleManualEntries > 0 ||\n dryRunResult.metrics.translatedEntries > 0;\n const hasAuditErrors = auditResult.issues.some((issue) => issue.severity === \"error\");\n\n console.log(\n JSON.stringify(\n {\n validation: validationResult,\n audit: auditResult,\n dryRun: dryRunResult.metrics,\n },\n null,\n 2,\n ),\n );\n if (hasValidationErrors || hasPendingSync || hasAuditErrors) {\n if (hasAuditErrors && !hasValidationErrors && !hasPendingSync) {\n throw new Error(\n \"Translation check failed because semantic audit provenance is missing, stale, or unresolved. Run ai-translate audit --refresh.\",\n );\n }\n throw new Error(\n \"Translation check failed. Run ai-translate sync to reconcile localized content.\",\n );\n }\n return 0;\n }\n case \"audit\": {\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const result = await auditCatalogs(config, {\n ...buildSyncOptions(parsed.options),\n checkOnly: parsed.options.auditCheck ?? false,\n refresh: parsed.options.refresh ?? false,\n });\n console.log(JSON.stringify(result, null, 2));\n if (result.issues.some((issue) => issue.severity === \"error\")) {\n throw new Error(\n parsed.options.auditCheck\n ? \"Semantic audit check failed. Run ai-translate audit --refresh.\"\n : \"Semantic audit completed with unresolved or unsafe translations.\",\n );\n }\n return 0;\n }\n case \"sync\": {\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n /*\n * The cache key is the full validation input, so a changed translation\n * gets a fresh entry. Sync validates the same entry once to decide\n * whether existing output is still valid and again while resolving\n * acceptance provenance; `check` has always deduplicated that pair.\n */\n const result = await withTranslationIssueCache(() =>\n syncWithSemanticAuditConvergence(config, buildSyncOptions(parsed.options)),\n );\n printSyncSummary(result.sync, result.audit, result.repairRounds);\n assertDryRunBudget(config, result.sync);\n assertSemanticAuditConvergence(result);\n return 0;\n }\n case \"new-locale\": {\n const locale = parsed.positionals[0];\n if (!locale) {\n throw new Error('The \"new-locale\" command requires a <locale> argument.');\n }\n\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const fromLocale = parsed.options.from ?? config.sourceLocale;\n const strategy = parsed.options.strategy ?? \"copy-source\";\n\n if (parsed.options.dryRun && fromLocale !== config.sourceLocale) {\n throw new Error(\n 'The \"new-locale\" command only supports --from <sourceLocale> when used with --dry-run.',\n );\n }\n\n if (parsed.options.dryRun && strategy !== \"copy-source\") {\n throw new Error(\n 'The \"new-locale\" command only supports --strategy copy-source when used with --dry-run.',\n );\n }\n\n if (strategy !== \"copy-source\" && fromLocale === config.sourceLocale) {\n throw new Error(\n `The \"${strategy}\" strategy requires --from <locale> to be a translated locale.`,\n );\n }\n\n const syncOptions: SyncCatalogsOptions = {\n ...buildSyncOptions(parsed.options),\n forceRetranslate: strategy === \"copy-locale-and-retranslate\",\n locales: [locale],\n };\n const transaction = parsed.options.dryRun\n ? {\n result: await convergeSemanticAudits(config, syncOptions),\n scaffoldResults: [],\n }\n : await runStagedCatalogTransaction(\n config,\n async (stagedConfig) => {\n const scaffoldResults = await scaffoldLocale(stagedConfig, locale, {\n fromLocale,\n strategy,\n });\n const result = await convergeSemanticAudits(stagedConfig, syncOptions);\n return { result, scaffoldResults };\n },\n ({ result }) => semanticAuditConvergenceError(result) === undefined,\n );\n const { result, scaffoldResults } = transaction;\n console.log(\n JSON.stringify(\n {\n dryRun: result.sync.dryRun,\n fromLocale,\n locale,\n metrics: result.sync.metrics,\n scaffoldResults,\n ...(result.audit === undefined\n ? {}\n : {\n semanticAudit: result.audit,\n semanticRepairRounds: result.repairRounds,\n }),\n strategy,\n status: semanticAuditConvergenceError(result) === undefined ? \"ok\" : \"failed\",\n },\n null,\n 2,\n ),\n );\n assertSemanticAuditConvergence(result);\n return 0;\n }\n case \"scaffold-locale\": {\n const locale = parsed.positionals[0];\n if (!locale) {\n throw new Error('The \"scaffold-locale\" command requires a <locale> argument.');\n }\n\n if (!parsed.options.from) {\n throw new Error('The \"scaffold-locale\" command requires --from <locale>.');\n }\n\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const scaffoldResults = await scaffoldLocale(config, locale, {\n fromLocale: parsed.options.from,\n strategy: parsed.options.strategy ?? \"copy-locale\",\n });\n console.log(\n JSON.stringify(\n {\n fromLocale: parsed.options.from,\n locale,\n scaffoldResults,\n strategy: parsed.options.strategy ?? \"copy-locale\",\n status: \"ok\",\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n case \"adopt\": {\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const result = await adoptExistingTranslations({\n catalogs: config.catalogs,\n identicalToSource: parsed.options.identicalToSource ?? \"adopt\",\n sourceLocale: config.sourceLocale,\n targetLocales: config.targetLocales,\n });\n\n if (!parsed.options.dryRun) {\n await config.state.save(result.state);\n }\n\n console.log(\n JSON.stringify(\n {\n adopted: result.adopted,\n dryRun: parsed.options.dryRun === true,\n identicalToSource: result.identicalToSource,\n status: \"ok\",\n untranslated: result.untranslated,\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n default:\n throw new Error(`Unknown command \"${parsed.command}\".`);\n }\n } catch (error) {\n console.error(\n error instanceof Error ? error.message : `Unexpected CLI failure: ${String(error)}`,\n );\n return 1;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AASA,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;AACF;AAEA,SAAS,oBAAoB,OAA4C;CACvE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,SACd,cAAc,SACd,kBAAkB,SAClB,WAAW,SACX,mBAAmB;AAEvB;AAEA,SAAgB,eAAe,KAAa,cAA+B;CACzE,IAAI,cACF,OAAO,KAAK,QAAQ,KAAK,YAAY;CAGvC,KAAK,MAAM,aAAa,mBAAmB;EACzC,MAAM,WAAW,KAAK,KAAK,KAAK,SAAS;EACzC,IAAI,WAAW,QAAQ,GACrB,OAAO;CAEX;CAEA,MAAM,IAAI,MACR,yCAAyC,IAAI,qBAAqB,kBAAkB,KAAK,IAAI,GAC/F;AACF;AAEA,eAAsB,aAAa,KAA8C;CAC/E,MAAM,UAAU,QAAQ,IAAI;CAC5B,MAAM,aAAa;EACjB;EACA;EACA,UAAU,QAAQ,YAAY,KAAA;EAC9B,UAAU,QAAQ,QAAQ,UAAU,KAAA;CACtC,CAAC,CAAC,QAAQ,UAA2B,UAAU,KAAA,CAAS;CAExD,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,YAAY,YAAY;EACjC,MAAM,WAAW,KAAK,KAAK,KAAK,QAAQ;EACxC,IAAI;GACF,MAAM,MAAM,MAAMA,SAAG,SAAS,UAAU,MAAM;GAC9C,OAAO,OAAO,QAAQC,MAAY,GAAG,CAAC;EACxC,SAAS,OAAO;GACd,IAAK,MAAgC,SAAS,UAC5C,MAAM;EAEV;CACF;CAEA,OAAW;EACT,UAAU;EACV,MAAM,WAAW,KAAK,cAAc,KAAK,KAAK,KAAK,SAAS,CAAC;EAC7D,YAAY,QAAQ;CACtB,CAAC;CAED,OAAO;AACT;AAEA,eAAsB,WACpB,KACA,cAC4D;CAC5D,MAAM,aAAa,eAAe,KAAK,YAAY;CAKnD,MAAM,SAAkB,MAJX,WAAW,YAAY,KAAK;EACvC,gBAAgB;EAChB,aAAa;CACf,CACiC,CAAC,CAAC,OAAO,UAAU;CACpD,MAAM,WACJ,OAAO,WAAW,YAAY,WAAW,QAAQ,aAAa,SAC1D,OAAO,WAAW,SAClB;CAEN,IAAI,CAAC,oBAAoB,QAAQ,GAC/B,MAAM,IAAI,MAAM,eAAe,WAAW,+CAA+C;CAG3F,OAAO;EACL,QAAQ,aAAa,QAAQ;EAC7B;CACF;AACF;;;AC3FA,MAAM,kBAAkB;AACxB,MAAM,yBAAyB;;AAG/B,MAAa,0BAAkD,CAAC,GAAGC,qBAAkB,gBAAgB;AA2BrG,SAAS,SAAS,OAAgC;CAChD,OAAO;EACL,YAAY,MAAM,YAAY;EAC9B,GAAG,MAAM,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,IAAI,KAAK,OAAO,EAAE;EACrE,qBAAqB,MAAM,KAAK,aAAa,IAAI,OAC/C,MAAM,KAAK,cAAc,MAC3B,EAAE,qBAAqB,MAAM,KAAK,cAAc,KAAK,IAAI;CAC3D;AACF;AAEA,eAAe,gBACb,KACA,MACA,SACmB;CACnB,MAAM,WAAW,uBAAuB,MAAM,OAAO;CAErD,IAAI;EACF,MAAM,MAAM,MAAMC,SAAG,SAAS,KAAK,KAAK,KAAK,cAAc,GAAG,MAAM;EACpE,MAAM,WAAW,KAAK,MAAM,GAAG;EAC/B,MAAM,2BAAW,IAAI,IAAI,CACvB,GAAG,OAAO,KAAK,SAAS,gBAAgB,CAAC,CAAC,GAC1C,GAAG,OAAO,KAAK,SAAS,mBAAmB,CAAC,CAAC,CAC/C,CAAC;EACD,OAAO,SAAS,QAAQ,SAAS,CAAC,SAAS,IAAI,IAAI,CAAC;CACtD,QAAQ;EACN,OAAO,CAAC,GAAG,QAAQ;CACrB;AACF;AAEA,SAAS,YACP,QACA,WACe;CACf,IAAI,cAAc,KAAA,GAAW;EAC3B,MAAM,QAAQ,OAAO,MAAM,UAAU,MAAM,kBAAkB,SAAS;EACtE,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MACR,MAAM,UAAU,iCACd,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC,CAAC,KAAK,IAAI,KAAK,OAC1D,EACH;EAEF,OAAO;CACT;CAEA,MAAM,CAAC,MAAM,GAAG,QAAQ;CACxB,IAAI,SAAS,KAAA,GACX,MAAM,IAAI,MACR,0aAIF;CAEF,IAAI,KAAK,SAAS,KAAK,KAAK,EAAE,EAAE,eAAe,KAAK,YAIlD,MAAM,IAAI,MACR,2CAA2C,OACxC,KAAK,UAAU,MAAM,aAAa,CAAC,CACnC,KAAK,IAAI,EAAE,6CAChB;CAEF,OAAO;AACT;;;;;;;;AASA,eAAsB,QAAQ,KAAa,UAAuB,CAAC,GAAwB;CACzF,MAAM,SAAS,MAAM,cACnB,KACA,EAAE,cAAc,QAAQ,gBAAgB,wBAAwB,CAClE;CACA,MAAM,QAAQ,YAAY,QAAQ,QAAQ,WAAW;CACrD,MAAM,WAAW,aAAa,MAAM,MAAM;EACxC,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;EAC9D,GAAI,QAAQ,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,QAAQ,SAAS;EACvE,GAAI,QAAQ,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,QAAQ,gBAAgB;CAC9F,CAAC;CACD,MAAM,aAAa,KAAK,KAAK,KAAK,eAAe;CACjD,MAAM,QAAQ,SAAS,KAAK;CAE5B,KAAK,MAAM,WAAW,MAAM,KAAK,UAC/B,MAAM,KAAK,OAAO,SAAS;CAG7B,MAAM,SAAS,OAAO,QAAQ,cAAc,cAAc,KAAK;CAC/D,IAAI,OAAO,SAAS,GAClB,MAAM,KACJ,4BAA4B,OAAO,KAAK,cAAc,UAAU,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE,EAC1F;CAGF,IAAI,QAAQ,YAAY,MAAM;EAC5B,MAAM,KAAK,IAAI,eAAe,gBAAgB,IAAI,IAAI,QAAQ;EAC9D,OAAO;GAAE,YAAY;GAAM;GAAO;EAAM;CAC1C;CAMA,IAAI,MAJiBA,SAClB,OAAO,UAAU,CAAC,CAClB,WAAW,IAAI,CAAC,CAChB,YAAY,KAAK,KACN,QAAQ,UAAU,MAC9B,MAAM,IAAI,MAAM,GAAG,gBAAgB,+CAA+C;CAGpF,MAAMA,SAAG,UAAU,YAAY,UAAU,MAAM;CAC/C,MAAM,KAAK,IAAI,SAAS,gBAAgB,IAAI,IAAI,aAAa;CAE7D,MAAM,UAAU,MAAM,gBAAgB,KAAK,MAAM,MAAM,OAAO;CAC9D,IAAI,OAAO;CACX,IAAI,QAAQ,SAAS,GACnB,MAAM,KAAK,KAAK,OAAO,MAAM,EAAE,aAAa,QAAQ,KAAK,GAAG,GAAG;CAEjE,MAAM,iBACJ,QAAQ,aAAa,WACjB,oBAAoB,QAAQ,mBAAmB,uBAAuB,mBACtE;CACN,MAAM,KACJ,KAAK,OAAO,MAAM,EAAE,QAAQ,eAAe,oCAC3C,KAAK,OAAO,MAAM,EAAE,wCAAwC,gBAAgB,IAC5E,KAAK,OAAO,MAAM,EAAE,6DACpB,KAAK,OAAO,MAAM,EAAE,0DACpB,KAAK,OAAO,IAAI,EAAE,wCACpB;CAEA,OAAO;EAAE;EAAY;EAAO;CAAM;AACpC;;;ACvJA,MAAM,kCAAkC,OAAO,IAC7C,uDACF;AAEA,SAAS,WAAW,OAA6C;CAC/D,OAAO,gBAAgB,KAAK;AAC9B;AAEA,SAAS,WAAW,OAAqB;CACvC,OAAO;EACL,GAAG;EACH,SAAS,MAAM,QAAQ,KAAK,aAAa,EAAE,GAAG,QAAQ,EAAE;EACxD,GAAI,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,gBAAgB,MAAM,OAAO,EAAE;EACjF,GAAI,MAAM,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,EAAE;EAC9D,GAAI,MAAM,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAO,KAAK,WAAW,EAAE,GAAG,MAAM,EAAE,EAAE;CAC9F;AACF;;;;AAKA,SAAS,cAAc,UAA0C;CAC/D,OAAO;EACL,SAAS,SAAS,QAAQ,IAAI,UAAU;EACxC,GAAI,SAAS,mBAAmB,KAAA,IAC5B,CAAC,IACD,EACE,gBAAgB;GACd,GAAI,SAAS,eAAe,qBAAqB,KAAA,IAC7C,CAAC,IACD,EAAE,kBAAkB,EAAE,GAAG,SAAS,eAAe,iBAAiB,EAAE;GACxE,GAAI,SAAS,eAAe,qBAAqB,KAAA,IAC7C,CAAC,IACD,EAAE,kBAAkB,CAAC,GAAG,SAAS,eAAe,gBAAgB,EAAE;EACxE,EACF;EACJ,KAAK,EAAE,GAAG,SAAS,IAAI;EACvB,OAAO,SAAS;EAChB,GAAI,SAAS,oBAAoB,KAAA,IAC7B,CAAC,IACD,EAAE,iBAAiB,SAAS,gBAAgB;CAClD;AACF;AAEA,SAAS,mBAAmB,UAA0B,KAAkC;CACtF,OAAO,cAAc;EAAE,GAAG;EAAU,KAAK,EAAE,GAAG,IAAI;CAAE,CAAC;AACvD;AAEA,SAAS,YAAY,KAA0B;CAC7C,OAAO;EAAC,IAAI;EAAW,IAAI;EAAQ,IAAI;EAAQ,IAAI;EAAM,IAAI;CAAM,CAAC,CAAC,KAAK,IAAQ;AACpF;AAEA,IAAM,mBAAN,MAAiD;CAC/C,QAAgB;CAChB;CAEA,YAAY,SAA4B;EACtC,KAAK,WAAW,WAAW,OAAO;CACpC;CAEA,aAAsB;EACpB,OAAO,KAAK;CACd;CAEA,OAAmC;EACjC,OAAO,QAAQ,QAAQ,WAAW,KAAK,QAAQ,CAAC;CAClD;CAEA,KAAK,OAAyC;EAC5C,KAAK,WAAW,WAAW,KAAK;EAChC,KAAK,QAAQ;EACb,OAAO,QAAQ,QAAQ;CACzB;CAEA,iBAAoC;EAClC,OAAO,WAAW,KAAK,QAAQ;CACjC;CAEA,SAAY,WAAyC;EACnD,OAAO,UAAU;CACnB;AACF;AASA,eAAe,aAAa,UAGzB;CACD,IAAI;EACF,MAAM,CAAC,UAAU,SAAS,MAAM,QAAQ,IAAI,CAACC,SAAG,SAAS,QAAQ,GAAGA,SAAG,KAAK,QAAQ,CAAC,CAAC;EACtF,OAAO;GAAE,MAAM,MAAM;GAAM;EAAS;CACtC,SAAS,OAAO;EACd,IAAK,MAAgC,SAAS,UAC5C,OAAO;GAAE,MAAM,KAAA;GAAW,UAAU;EAAK;EAE3C,MAAM;CACR;AACF;AAEA,eAAe,gBAAgB,UAAkB,UAAkB,MAA8B;CAC/F,MAAMA,SAAG,MAAM,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;CAC1D,MAAM,gBAAgB,KAAK,KACzB,KAAK,QAAQ,QAAQ,GACrB,IAAI,KAAK,SAAS,QAAQ,EAAE,gBAAgB,WAAW,GACzD;CACA,IAAI;EACF,MAAMA,SAAG,UAAU,eAAe,QAAQ;EAC1C,IAAI,SAAS,KAAA,GACX,MAAMA,SAAG,MAAM,eAAe,IAAI;EAEpC,MAAMA,SAAG,OAAO,eAAe,QAAQ;CACzC,UAAU;EACR,MAAMA,SAAG,GAAG,eAAe,EAAE,OAAO,KAAK,CAAC;CAC5C;AACF;AAEA,IAAM,iBAAN,MAAqB;CAMA;CACA;CANnB,wBAAyB,IAAI,IAAwB;CACrD,8BAA+B,IAAI,IAA2D;CAC9F;CAEA,YACE,UACA,cACA;EAFiB,KAAA,WAAA;EACA,KAAA,eAAA;CAChB;CAEH,WAAsC;EACpC,OAAO,KAAK,SAAS,KAAK,YAAY,KAAK,cAAc,OAAO,CAAC;CACnE;CAEA,MAAM,UAAyB;EAC7B,IAAI,KAAK,aAAa,KAAA,GACpB,MAAMA,SAAG,GAAG,KAAK,UAAU;GAAE,OAAO;GAAM,WAAW;EAAK,CAAC;CAE/D;CAEA,MAAM,UAAyB;EAC7B,KAAK,MAAM,UAAU,KAAK,MAAM,OAAO,GACrC,MAAM,gBAAgB,OAAO,UAAU,MAAMA,SAAG,SAAS,OAAO,QAAQ,GAAG,OAAO,IAAI;CAE1F;CAEA,MAAM,kBAAiC;EACrC,MAAM,QAAQ,IAAI,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,WAAW;GAC/D,MAAM,UAAU,MAAM,aAAa,OAAO,QAAQ;GAIlD,IAAI,EAHc,QAAQ,aAAa,OACnC,OAAO,aAAa,OACpB,OAAO,aAAa,QAAQ,QAAQ,SAAS,OAAO,OAAO,QAAQ,MACrD,QAAQ,SAAS,OAAO,MACxC,MAAM,IAAI,MAAM,iDAAiD,OAAO,SAAS,iEAAiE;EAEtJ,CAAC,CAAC;CACJ;CAEA,MAAM,iBAA4D;EAChE,OAAQ,QAAQ,IACd,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,YAAY;GAC9C,GAAI,OAAO,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK;GACzD,MAAM,MAAMA,SAAG,SAAS,OAAO,QAAQ;GACvC,UAAU,OAAO;GACjB,MAAM,OAAO;EACf,EAAE,CACJ;CACF;CAEA,MAAM,WAA0B;EAC9B,MAAM,WAAsB,CAAC;EAC7B,KAAK,MAAM,UAAU,KAAK,MAAM,OAAO,GACrC,IAAI;GACF,IAAI,OAAO,aAAa,MACtB,MAAMA,SAAG,GAAG,OAAO,UAAU,EAAE,OAAO,KAAK,CAAC;QAE5C,MAAM,gBAAgB,OAAO,UAAU,OAAO,UAAU,OAAO,IAAI;EAEvE,SAAS,OAAO;GACd,SAAS,KAAK,KAAK;EACrB;EAEF,IAAI,SAAS,SAAS,GACpB,MAAM,IAAI,eAAe,UAAU,qDAAqD;CAE5F;CAEA,MAAc,UAAU,UAAuC;EAC7D,MAAM,WAAW,KAAK,MAAM,IAAI,QAAQ;EACxC,IAAI,UACF,OAAO;EAET,KAAK,aAAa,MAAMA,SAAG,QAAQ,KAAK,KAAK,GAAG,OAAO,GAAG,qBAAqB,CAAC;EAChF,MAAM,EAAE,MAAM,aAAa,MAAM,aAAa,QAAQ;EACtD,MAAM,WAAW,KAAK,KACpB,KAAK,UACL,GAAG,OAAO,KAAK,MAAM,IAAI,IAAI,KAAK,QAAQ,QAAQ,KAAK,aACzD;EACA,IAAI,aAAa,MACf,MAAMA,SAAG,UAAU,UAAU,QAAQ;EAEvC,MAAM,SAAS;GAAE;GAAM;GAAU;GAAU;EAAS;EACpD,KAAK,MAAM,IAAI,UAAU,MAAM;EAC/B,OAAO;CACT;CAEA,MAAc,WACZ,SACA,KACgC;EAChC,MAAM,SAAS,KAAK,MAAM,IAAI,IAAI,IAAI;EACtC,IAAI,CAAC,QAAQ;GACX,MAAM,WAAW,MAAM,QAAQ,aAAa,GAAG;GAC/C,OAAO,aAAa,OAAO,OAAO,cAAc,QAAQ;EAC1D;EACA,MAAM,UAAU;GAAE,GAAG;GAAK,MAAM,OAAO;EAAS;EAChD,MAAM,WAAW,MAAM,QAAQ,aAAa,OAAO;EACnD,OAAO,aAAa,OAAO,OAAO,mBAAmB,UAAU,GAAG;CACpE;CAEA,MAAc,YAAY,SAAyB,UAAyC;EAC1F,MAAM,SAAS,MAAM,KAAK,UAAU,SAAS,IAAI,IAAI;EACrD,MAAM,UAAU;GAAE,GAAG,SAAS;GAAK,MAAM,OAAO;EAAS;EACzD,MAAM,iBAAiB,MAAM,QAAQ,aAAa,OAAO;EACzD,MAAM,QAAQ,cAAc;GAC1B,GAAG,cAAc,QAAQ;GACzB,KAAK;GAKL,OACE,mBAAmB,QAAQ,QAAQ,qBAAqB,KAAA,IACpD,SAAS,QACT,QAAQ,iBAAiB;IAAE;IAAU,QAAQ;GAAe,CAAC;EACrE,CAAC;EAED,IAAI,MADoB,QAAQ,aAAa,OAAO,MAClC,MAChB,MAAM,IAAI,MACR,YAAY,QAAQ,GAAG,oCAAoC,SAAS,IAAI,KAAK,EAC/E;EAEF,KAAK,YAAY,IAAI,YAAY,SAAS,GAAG,GAAG;GAAE;GAAS,KAAK,EAAE,GAAG,SAAS,IAAI;EAAE,CAAC;EAKrF,KAAK,MAAM,WAAW,KAAK,YAAY,OAAO,GAC5C,IAAI,QAAQ,IAAI,SAAS,SAAS,IAAI,MAAM;GAC1C,MAAM,iBAAiB;IAAE,GAAG,QAAQ;IAAK,MAAM,OAAO;GAAS;GAC/D,IAAK,MAAM,QAAQ,QAAQ,aAAa,cAAc,MAAO,MAC3D,MAAM,IAAI,MACR,YAAY,QAAQ,QAAQ,GAAG,qCAAqC,QAAQ,IAAI,KAAK,EACvF;EAEJ;CAEJ;CAEA,cAAsB,SAAyC;EAC7D,MAAM,mBAAmB,QAAQ,kBAAkB,KAAK,OAAO;EAC/D,OAAO;GACL,oBAAoB,WAAW,WAAW,QAAQ,kBAAkB,WAAW,MAAM;GACrF,GAAI,QAAQ,2BAA2B,KAAA,IACnC,CAAC,IACD,EAAE,wBAAwB,QAAQ,uBAAuB,KAAK,OAAO,EAAE;GAC3E,IAAI,QAAQ;GACZ,GAAI,QAAQ,mBAAmB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,QAAQ,eAAe;GACzF,GAAI,QAAQ,2BAA2B,KAAA,IACnC,CAAC,IACD,EAAE,wBAAwB,QAAQ,uBAAuB,KAAK,OAAO,EAAE;GAC3E,mBAAmB,iBAAiB,QAAQ,iBAAiB,YAAY;GACzE,eAAe,QAAQ,KAAK,WAAW,SAAS,GAAG;GACnD,GAAI,qBAAqB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB;GAC7D,mBAAmB,OAAO,SAAS;IASjC,OAAO,cAAc,MARE,QAAQ,kBAAkB;KAC/C,GAAI,KAAK,YAAY,KAAA,IACjB,CAAC,IACD,EAAE,SAAS,KAAK,QAAQ,KAAK,UAAU,gBAAgB,KAAK,CAAC,EAAE;KACnE,KAAK,EAAE,GAAG,KAAK,IAAI;KACnB,QAAQ,cAAc,KAAK,MAAM;KACjC,QAAQ,KAAK,WAAW,OAAO,OAAO,cAAc,KAAK,MAAM;IACjE,CAAC,CAC4B;GAC/B;GACA,GAAI,QAAQ,mBAAmB,KAAA,IAC3B,CAAC,IACD,EACE,iBAAiB,YACf,KAAK,gBAAgB,SAAS,OAAO,EACzC;GACJ,gBAAgB,aAAa,KAAK,YAAY,SAAS,QAAQ;EACjE;CACF;CAEA,MAAc,gBACZ,SACA,SAC+B;EAC/B,MAAM,WAAW,QAAQ,YAAY;EACrC,MAAM,aACJ,aAAa,gBAAgB,KAAK,eAAgB,QAAQ,cAAc,KAAK;EAC/E,MAAM,OAAO,MAAM,QAAQ,iBAAiB,UAAU;EACtD,IAAI,aAAa,SACf,OAAO;GACL,WAAW,QAAQ;GACnB,kBAAkB;GAClB,QAAQ,QAAQ;GAChB,kBAAkB,KAAK;GACvB;EACF;EAGF,IAAI,mBAAmB;EACvB,IAAI,mBAAmB;EACvB,MAAM,UAAU,KAAK,cAAc,OAAO;EAC1C,KAAK,MAAM,aAAa,MAAM;GAC5B,MAAM,YAAY,QAAQ,kBAAkB,WAAW,QAAQ,MAAM;GACrE,IAAK,MAAM,QAAQ,aAAa,SAAS,MAAO,MAAM;IACpD,oBAAoB;IACpB;GACF;GACA,MAAM,SAAS,MAAM,QAAQ,aAAa,SAAS;GACnD,IAAI,WAAW,MAAM;IACnB,oBAAoB;IACpB;GACF;GACA,MAAM,kBAAkB,QAAQ,2BAA2B,KAAA,KAAa,QAAQ,2BAA2B,KAAA,IACvG,SACA,MAAM,QAAQ,uBAAuB;IAAE,QAAQ,QAAQ;IAAQ;GAAO,CAAC;GAC3E,MAAM,WAAW,QAAQ,2BAA2B,KAAA,IAChD,MAAM,QAAQ,kBAAkB;IAAE,KAAK;IAAW,QAAQ;IAAiB,QAAQ;GAAK,CAAC,IACzF,MAAM,QAAQ,uBAAuB;IAAE,KAAK;IAAW,QAAQ;IAAiB;GAAS,CAAC;GAC9F,IAAI,aAAa,MAAM;IACrB,oBAAoB;IACpB;GACF;GACA,MAAM,QAAQ,cAAc,QAAQ;GACpC,oBAAoB;EACtB;EAEA,OAAO;GACL,WAAW,QAAQ;GACnB;GACA,QAAQ,QAAQ;GAChB;GACA;EACF;CACF;AACF;AAEA,SAAS,cAAc,aAAsB,gBAA2C;CACtF,OAAO,eAAe,WAAW,IAC7B,uBAAuB,QACrB,cACA,IAAI,MAAM,OAAO,WAAW,CAAC,IAC/B,IAAI,eACF,CAAC,aAAa,GAAG,cAAc,GAC/B,oEACF;AACN;AAUA,SAAS,kBAAkB,OAAwD;CACjF,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM;EAC/C,MAAM,YAAa,MACjB;EAEF,IACE,OAAO,cAAc,YACrB,cAAc,QACd,YAAY,aACZ,OAAO,UAAU,WAAW,YAE5B,OAAO;CAEX;CACA,OAAO;AACT;AAEA,eAAsB,4BACpB,QACA,WACA,qBAA6C,MAC7C,OACY;CAQZ,MAAM,YAAY,mBAAmB,OAAO,KAAK,IAAI,QAAQ,KAAA;CAE7D,OAAO,OAAO,MAAM,SAAS,YAAY;EACvC,MAAM,eAAe,MAAM,OAAO,MAAM,KAAK,SAAS;EACtD,MAAM,cAAc,IAAI,iBAAiB,YAAY;EACrD,MAAM,iBAAiB,IAAI,eAAe,OAAO,UAAU,OAAO,YAAY;EAC9E,MAAM,eAAkC;GACtC,GAAG;GACH,UAAU,eAAe,SAAS;GAClC,OAAO;EACT;EACA,IAAI;GACF,MAAM,SAAS,MAAM,UAAU,YAAY;GAC3C,IAAI,CAAC,aAAa,MAAM,GACtB,OAAO;GAMT,MAAM,eAAe,gBAAgB;GACrC,MAAM,eAAe,kBAAkB,OAAO,KAAK;GACnD,IAAI,iBAAiB,MAAM;IACzB,MAAM,YAAY,MAAM,eAAe,eAAe;IACtD,IAAI,UAAU,SAAS,KAAK,YAAY,WAAW,GACjD,MAAM,aAAa,OAAO;KACxB;KACA,cAAc,WAAW,YAAY;KACrC,WAAW,YAAY,eAAe;KACtC,GAAI,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,UAAU;IACxD,CAAC;GAEL,OAAO;IACL,IAAI,qBAAqB;IACzB,IAAI;KACF,MAAM,eAAe,QAAQ;KAC7B,IAAI,YAAY,WAAW,GAAG;MAC5B,qBAAqB;MACrB,MAAM,OAAO,MAAM,KAAK,YAAY,eAAe,GAAG,SAAS;KACjE;IACF,SAAS,OAAO;KACd,MAAM,iBAA4B,CAAC;KACnC,IAAI;MACF,MAAM,eAAe,SAAS;KAChC,SAAS,eAAe;MACtB,eAAe,KAAK,aAAa;KACnC;KACA,IAAI,oBACF,IAAI;MACF,MAAM,OAAO,MAAM,KAAK,WAAW,YAAY,GAAG,SAAS;KAC7D,SAAS,eAAe;MACtB,eAAe,KAAK,aAAa;KACnC;KAEF,MAAM,cAAc,OAAO,cAAc;IAC3C;GACF;GACA,OAAO;EACT,UAAU;GACR,MAAM,eAAe,QAAQ;EAC/B;CACF,CAAC;AACH;;;AC7aA,SAAS,mBAAmB,YAAoB,OAAmC;CACjF,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,aAAa,WAAW,oBAAoB;CAG9D,OAAO;AACT;AAEA,SAAS,sBAAsB,OAA+B;CAC5D,IAAI,UAAU,YAAY,UAAU,UAClC,MAAM,IAAI,MAAM,0DAA0D,MAAM,GAAG;CAGrF,OAAO;AACT;AAEA,SAAS,+BAA+B,OAAwC;CAC9E,IAAI,UAAU,WAAW,UAAU,QACjC,MAAM,IAAI,MACR,kEAAkE,MAAM,GAC1E;CAGF,OAAO;AACT;AAEA,SAAS,gCAAgC,YAAoB,OAAmC;CAC9F,MAAM,WAAW,mBAAmB,YAAY,KAAK;CACrD,MAAM,cAAc,OAAO,QAAQ;CACnC,IAAI,CAAC,OAAO,cAAc,WAAW,KAAK,cAAc,GACtD,MAAM,IAAI,MAAM,aAAa,WAAW,mCAAmC;CAE7E,OAAO;AACT;AAEA,eAAe,eACb,QACA,YACA,SAC2B;CAE3B,OAAO;EACL,GAAG,MAFgB,iBAAiB,QAAQ,OAAO;EAGnD;CACF;AACF;AAEA,MAAM,iCAAiC;AAQvC,SAAS,iBACP,QACA,eACA,uBAAuB,GACjB;CACN,MAAM,4BAA4B,mCAAmC,MAAM;CAC3E,MAAM,0BAA0B,iCAAiC,MAAM;CACvE,QAAQ,IACN,KAAK,UACH;EACE,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,GAAI,OAAO,UAAU,OAAO,KAAK,yBAAyB,CAAC,CAAC,SAAS,IACjE,EAAE,0BAA0B,IAC5B,CAAC;EACL,GAAI,kBAAkB,KAAA,IAAY,CAAC,IAAI;GAAE;GAAe;EAAqB;EAC7E,GAAI,4BAA4B,KAAA,IAAY,CAAC,IAAI,EAAE,wBAAwB;CAC7E,GACA,MACA,CACF,CACF;AACF;AAEA,SAAS,iCAAiC,QAY5B;CACZ,IAAI,OAAO,QAAQ,kBAAkB,GACnC;CAEF,MAAM,SAAS,OAAO,UAAU,SAAS,aACvC,SAAS,OACN,QAAQ,UAAU,MAAM,aAAa,OAAO,CAAC,CAC7C,KAAK,WAAW;EACf,WAAW,SAAS;EACpB,MAAM,MAAM;EACZ,QAAQ,SAAS;EACjB,SAAS,MAAM;EACf,MAAM,SAAS;EACf,QAAQ,SAAS;CACnB,EAAE,CACN;CACA,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,SAAS,QAClB,OAAO,MAAM,SAAS,OAAO,MAAM,SAAS,KAAK;CAEnD,OAAO;EACL,QAAQ,OAAO,YACb,OAAO,QAAQ,MAAM,CAAC,CAAC,UACpB,CAAC,UAAU,YAAY,CAAC,WAAW,gBAClC,aAAa,aAAa,SAAS,cAAc,SAAS,CAC9D,CACF;EACA,UAAU,OAAO,MAAM,GAAG,EAAE;CAC9B;AACF;AAEA,SAAS,mCAAmC,QAA4C;CACtF,MAAM,UAAkC,CAAC;CACzC,KAAK,MAAM,YAAY,OAAO,WAC5B,KAAK,MAAM,CAAC,QAAQ,UAAU,OAAO,QAAQ,SAAS,6BAA6B,CAAC,CAAC,GACnF,QAAQ,WAAW,QAAQ,WAAW,KAAK;CAG/C,OAAO,OAAO,YACZ,OAAO,QAAQ,OAAO,CAAC,CAAC,UACrB,CAAC,YAAY,YAAY,CAAC,aAAa,gBACtC,aAAa,aAAa,WAAW,cAAc,WAAW,CAClE,CACF;AACF;AAEA,SAAS,kBAAkB,QAA2B,QAAwC;CAC5F,IAAI,CAAC,OAAO,UAAU,OAAO,YAAY,iBAAiB,KAAA,GACxD;CAEF,MAAM,SAAS,OAAO,WAAW;CACjC,IACE,OAAO,2BAA2B,KAAA,KAClC,OAAO,QAAQ,oBAAoB,OAAO,wBAE1C,OACE,+BAA+B,OAC7B,OAAO,QAAQ,iBACjB,EAAE,6DACoC,OAAO,OAAO,sBAAsB,EAAE;CAGhF,MAAM,UAAU,mCAAmC,MAAM;CACzD,MAAM,aAAa,OAAO,sCAAsC,CAAC,EAAA,CAAG,QACjE,YAAY,QAAQ,WAAW,KAAK,CACvC;CACA,OAAO,UAAU,WAAW,IACxB,KAAA,IACA,6DAA6D,UAC1D,KAAK,WAAW,GAAG,OAAO,IAAI,OAAO,QAAQ,WAAW,CAAC,EAAE,EAAE,CAAC,CAC9D,KAAK,IAAI,EAAE;AACpB;AAEA,SAAS,mBAAmB,QAA2B,QAA0B;CAC/E,MAAM,QAAQ,kBAAkB,QAAQ,MAAM;CAC9C,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,KAAK;AAEzB;AAEA,eAAe,uBACb,QACA,SACyC;CACzC,IAAI,OAAO,MAAM,aAAa,QAAQ,OAAO;CAC7C,IACE,QAAQ,WAAW,QACnB,KAAK,QAAQ,gBAAgB,MAC5B,OAAO,gBAAgB,UAAU,OAAO,KACzC,uBAAuB,MAAM,GAE7B,OAAO;EAAE,OAAO,KAAA;EAAW,cAAc;EAAG;CAAK;CAGnD,IAAI,QAAQ,MAAM,cAAc,QAAQ,OAAO;CAC/C,IAAI,eAAe;CACnB,MAAM,0BACJ,OAAO,YAAY,0BAA0B;CAC/C,MAAM,gBAAgB,EAAE,GAAG,QAAQ;CACnC,OAAO,cAAc;CACrB,OAAO,cAAc;CACrB,OAAO,MAAM,cAAc,KAAK,eAAe,yBAAyB;EACtE,gBAAgB;EAChB,OAAO,MAAM,aAAa,QAAQ,aAAa;EAC/C,IAAI,KAAK,QAAQ,gBAAgB,GAC/B;EAEF,QAAQ,MAAM,cAAc,QAAQ,OAAO;CAC7C;CAEA,OAAO;EAAE;EAAO;EAAc;CAAK;AACrC;AAEA,eAAe,iCACb,QACA,SACyC;CACzC,IAAI,QAAQ,WAAW,MACrB,OAAO,uBAAuB,QAAQ,OAAO;CAE/C,OAAO,4BACL,SACC,iBAAiB,uBAAuB,cAAc,OAAO,IAC7D,WAAW,8BAA8B,MAAM,MAAM,KAAA,GACtD,kBAAkB,QAAQ,OAAO,CACnC;AACF;AAEA,SAAS,8BAA8B,QAA4D;CACjG,IAAI,OAAO,KAAK,QAAQ,gBAAgB,GACtC,OAAO;CAET,KAAK,OAAO,OAAO,cAAc,KAAK,GACpC,OAAO;CAET,KAAK,OAAO,OAAO,eAAe,KAAK,GACrC,OAAO,8CAA8C,OACnD,OAAO,YACT,EAAE;CAEJ,IAAI,OAAO,OAAO,OAAO,MAAM,UAAU,MAAM,aAAa,OAAO,GACjE,OAAO;AAGX;AAEA,SAAS,+BAA+B,QAA8C;CACpF,MAAM,QAAQ,8BAA8B,MAAM;CAClD,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,KAAK;AAEzB;AAEA,SAAS,iBAAiB,SAA8C;CACtE,MAAM,cAAmC,CAAC;CAC1C,IAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS,GACpD,YAAY,aAAa,QAAQ;CAGnC,IAAI,QAAQ,WAAW,KAAA,GACrB,YAAY,SAAS,QAAQ;CAG/B,IAAI,QAAQ,qBAAqB,KAAA,GAC/B,YAAY,mBAAmB,QAAQ;CAGzC,IAAI,QAAQ,yBAAyB,QAAQ,sBAAsB,SAAS,GAAG;EAC7E,YAAY,mBAAmB;EAC/B,YAAY,wBAAwB,QAAQ;CAC9C;CAEA,IAAI,QAAQ,gBAAgB,QAAQ,aAAa,SAAS,GACxD,YAAY,eAAe,QAAQ;CAGrC,IAAI,QAAQ,WAAW,QAAQ,QAAQ,SAAS,GAC9C,YAAY,UAAU,QAAQ;CAGhC,IAAI,QAAQ,2BAA2B,KAAA,GACrC,YAAY,yBAAyB,QAAQ;CAG/C,IAAI,QAAQ,WAAW,QAAQ,QAAQ,SAAS,GAC9C,YAAY,UAAU,QAAQ;CAGhC,OAAO;AACT;AAEA,SAAS,oBACP,OACA,SACmB;CACnB,IAAI,YAAY,KAAA,KAAa,QAAQ,WAAW,GAC9C,OAAO;CAET,MAAM,WAAW,IAAI,IAAI,OAAO;CAChC,OAAO;EACL,SAAS,OAAO,YACd,OAAO,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,GAAG,WAAW,SAAS,IAAI,MAAM,MAAM,CAAC,CAChF;EACA,SAAS,MAAM;CACjB;AACF;AAEA,SAAS,wBAAwB,OAAmC;CAClE,OAAO,OAAO,OAAO,MAAM,OAAO,CAAC,CAAC,MACjC,UAAU,OAAO,KAAK,MAAM,oBAAoB,CAAC,CAAC,CAAC,CAAC,SAAS,CAChE;AACF;AAEA,MAAM,uBAAuB;CAC3B,UAAU;CACV,SAAS;CACT,QAAQ;CACR,SAAS;CACT,QAAQ,CAAC;CACT,aAAa;CACb,YAAY;AACd;AAEA,eAAe,eACb,QACA,QACA,UAGI,CAAC,GACL;CACA,OAAO,QAAQ,IACb,OAAO,SAAS,IAAI,OAAO,YAAY;EACrC,IAAI,CAAC,QAAQ,gBACX,OAAO;EAGT,OAAQ,QAAQ,eAAe;GAC7B,GAAI,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,QAAQ,WAAW;GAC7E;GACA,GAAI,QAAQ,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,QAAQ,SAAS;EACzE,CAAC;CACH,CAAC,CACH;AACF;AAEA,SAAS,YAAkB;CACzB,QAAQ,IAAI;;;;;;;;;;;;yBAYW;AACzB;AAEA,SAAS,aAAa,MAAwC;CAC5D,MAAM,UAA0B,CAAC;CACjC,MAAM,cAAwB,CAAC;CAC/B,IAAI;CAEJ,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;EACnD,MAAM,MAAM,KAAK;EACjB,IAAI,QAAQ,KAAA,GACV;EAGF,IAAI,QAAQ,YAAY,QAAQ,MAC9B,OAAO;GACL,SAAS;GACT;GACA;EACF;EAGF,IAAI,QAAQ,eAAe,QAAQ,MACjC,OAAO;GACL,SAAS;GACT;GACA;EACF;EAGF,IAAI,IAAI,WAAW,IAAI,GAAG;GACxB,MAAM,CAAC,OAAO,IAAI,eAAe,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;GAC1D,IAAI,KAAK,WAAW,GAClB,MAAM,IAAI,MAAM,mCAAmC;GAGrD,MAAM,YAAY,eAAe,KAAK,QAAQ;GAC9C,QAAQ,MAAR;IACE,KAAK;KACH,QAAQ,aAAa;KACrB;IACF,KAAK;KACH,QAAQ,SAAS,mBAAmB,MAAM,SAAS;KACnD,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,CAAC,QAAQ,eAAe,CAAC,EAAA,CAAG,KAAK,mBAAmB,MAAM,SAAS,CAAC;KACpE,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,SAAS;KACjB;IACF,KAAK;KACH,QAAQ,QAAQ;KAChB;IACF,KAAK;KACH,QAAQ,mBAAmB;KAC3B;IACF,KAAK;KACH,CAAC,QAAQ,0BAA0B,CAAC,EAAA,CAAG,KAAK,mBAAmB,MAAM,SAAS,CAAC;KAC/E,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,OAAO,mBAAmB,MAAM,SAAS;KACjD,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,CAAC,QAAQ,iBAAiB,CAAC,EAAA,CAAG,KAAK,mBAAmB,MAAM,SAAS,CAAC;KACtE,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,cAAc,mBAAmB,MAAM,SAAS;KACxD,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,CAAC,QAAQ,YAAY,CAAC,EAAA,CAAG,KAAK,mBAAmB,MAAM,SAAS,CAAC;KACjE,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,QAAQ,mBAAmB,MAAM,SAAS;KAClD,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,UAAU;KAClB;IACF,KAAK;KACH,QAAQ,WAAW,mBAAmB,MAAM,SAAS;KACrD,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,kBAAkB,mBAAmB,MAAM,SAAS;KAC5D,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,yBAAyB,gCAAgC,MAAM,SAAS;KAChF,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,oBAAoB,+BAC1B,mBAAmB,MAAM,SAAS,CACpC;KACA,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,KAAK;KACH,QAAQ,UAAU;KAClB;IACF,KAAK;KAEH,QAAQ,WADS,mBAAmB,MAAM,SAChB;KAC1B,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IAEF,KAAK;KACH,CAAC,QAAQ,YAAY,CAAC,EAAA,CAAG,KAAK,mBAAmB,MAAM,SAAS,CAAC;KACjE,IAAI,gBAAgB,KAAA,GAClB,SAAS;KAEX;IACF,SACE,MAAM,IAAI,MAAM,qBAAqB,KAAK,GAAG;GACjD;GAEA;EACF;EAEA,IAAI,CAAC,SAAS;GACZ,UAAU;GACV;EACF;EAEA,YAAY,KAAK,GAAG;CACtB;CAEA,MAAM,gBAA+B;EACnC;EACA;CACF;CACA,IAAI,YAAY,KAAA,GACd,cAAc,UAAU;CAG1B,OAAO;AACT;AAEA,eAAsB,OACpB,OAA0B,QAAQ,KAAK,MAAM,CAAC,GAC9C,MAAc,QAAQ,IAAI,GACT;CACjB,IAAI;EACF,MAAM,SAAS,aAAa,IAAI;EAChC,IAAI,CAAC,OAAO,WAAW,OAAO,YAAY,QAAQ;GAChD,UAAU;GACV,OAAO;EACT;EAEA,IAAI,OAAO,YAAY,WAAW;GAChC,QAAQ,IAAI,OAAO;GACnB,OAAO;EACT;EAEA,QAAQ,OAAO,SAAf;GACE,KAAK,QAAQ;IAEX,MAAM,SAAS,MAAM,QAAQ,KAAK;KAChC,OAAO,OAAO,QAAQ,UAAU;KAChC,GAAI,OAAO,QAAQ,gBAAgB,KAAA,IAC/B,CAAC,IACD,EAAE,aAAa,OAAO,QAAQ,YAAY;KAC9C,GAAI,OAAO,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,OAAO,QAAQ,MAAM;KAC5E,SAAS,OAAO,QAAQ,YAAY,QAAQ,OAAO,QAAQ,WAAW;KACtE,GAAI,OAAO,QAAQ,aAAa,KAAA,IAC5B,CAAC,IACD,EAAE,UAAU,sBAAsB,OAAO,QAAQ,QAAQ,EAAE;KAC/D,GAAI,OAAO,QAAQ,oBAAoB,KAAA,IACnC,CAAC,IACD,EAAE,iBAAiB,OAAO,QAAQ,gBAAgB;IACxD,CAAC;IACD,QAAQ,IAAI,OAAO,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO;GACT;GACA,KAAK,YAAY;IACf,MAAM,aAAa,GAAG;IACtB,MAAM,EAAE,QAAQ,eAAe,MAAM,WAAW,KAAK,OAAO,QAAQ,MAAM;IAC1E,MAAM,UAAU,MAAM,eAAe,QAAQ,YAAY,iBAAiB,OAAO,OAAO,CAAC;IACzF,QAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;IAC5C,IAAI,QAAQ,OAAO,MAAM,UAAU,MAAM,aAAa,OAAO,GAC3D,MAAM,IAAI,MAAM,oBAAoB;IAEtC,OAAO;GACT;GACA,KAAK,SAAS;IACZ,MAAM,aAAa,GAAG;IACtB,MAAM,EAAE,QAAQ,eAAe,MAAM,WAAW,KAAK,OAAO,QAAQ,MAAM;IAC1E,MAAM,eAAoC;KACxC,GAAG,iBAAiB,OAAO,OAAO;KAClC,GAAI,QAAQ,IAAI,qCAAqC,MACjD,EAAE,iBAAiB,KAAK,IACxB,CAAC;IACP;IAIA,MAAM,gBAAgB,oBACpB,MAAM,OAAO,MAAM,KACjB,aAAa,YAAY,KAAA,IAAY,KAAA,IAAY,EAAE,SAAS,aAAa,QAAQ,CACnF,GACA,aAAa,OACf;IACA,MAAM,cAAiC;KACrC,GAAG;KACH,OAAO;MACL,YAAY,QAAQ,QAAQ,aAAa;MACzC,YACE,QAAQ,uBAAO,IAAI,MAAM,qDAAqD,CAAC;MACjF,WAAW,cAAc,OAAO,MAAM,SAAS,SAAS;KAC1D;IACF;IACA,MAAM,sBACH,YAAY,gBAAgB,UAAU,KAAK,KAAK,wBAAwB,aAAa;IACxF,MAAM,EAAE,aAAa,cAAc,qBAAqB,MAAM,0BAC5D,YAAY;KACV,MAAM,oBAAoB,MAAM,eAAe,aAAa,YAAY;MACtE,GAAG;MACH,4BAA4B;KAC9B,CAAC;KACD,MAAM,gBAAgB,MAAM,aAAa,aAAa;MACpD,GAAG;MACH,QAAQ;KACV,CAAC;KAOD,OAAO;MACL,aAPmB,qBACjB,MAAM,cAAc,aAAa;OAC/B,GAAG;OACH,WAAW;MACb,CAAC,IACD;MAGF,cAAc;MACd,kBAAkB;KACpB;IACF,CACF;IACA,MAAM,sBAAsB,iBAAiB,OAAO,MACjD,UAAU,MAAM,aAAa,OAChC;IACA,MAAM,iBACJ,aAAa,QAAQ,mBAAmB,KACxC,aAAa,QAAQ,gBAAgB,KACrC,aAAa,QAAQ,qBAAqB,KAC1C,aAAa,QAAQ,oBAAoB;IAC3C,MAAM,iBAAiB,YAAY,OAAO,MAAM,UAAU,MAAM,aAAa,OAAO;IAEpF,QAAQ,IACN,KAAK,UACH;KACE,YAAY;KACZ,OAAO;KACP,QAAQ,aAAa;IACvB,GACA,MACA,CACF,CACF;IACA,IAAI,uBAAuB,kBAAkB,gBAAgB;KAC3D,IAAI,kBAAkB,CAAC,uBAAuB,CAAC,gBAC7C,MAAM,IAAI,MACR,gIACF;KAEF,MAAM,IAAI,MACR,iFACF;IACF;IACA,OAAO;GACT;GACA,KAAK,SAAS;IACZ,MAAM,aAAa,GAAG;IACtB,MAAM,EAAE,WAAW,MAAM,WAAW,KAAK,OAAO,QAAQ,MAAM;IAC9D,MAAM,SAAS,MAAM,cAAc,QAAQ;KACzC,GAAG,iBAAiB,OAAO,OAAO;KAClC,WAAW,OAAO,QAAQ,cAAc;KACxC,SAAS,OAAO,QAAQ,WAAW;IACrC,CAAC;IACD,QAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;IAC3C,IAAI,OAAO,OAAO,MAAM,UAAU,MAAM,aAAa,OAAO,GAC1D,MAAM,IAAI,MACR,OAAO,QAAQ,aACX,mEACA,kEACN;IAEF,OAAO;GACT;GACA,KAAK,QAAQ;IACX,MAAM,aAAa,GAAG;IACtB,MAAM,EAAE,WAAW,MAAM,WAAW,KAAK,OAAO,QAAQ,MAAM;IAO9D,MAAM,SAAS,MAAM,gCACnB,iCAAiC,QAAQ,iBAAiB,OAAO,OAAO,CAAC,CAC3E;IACA,iBAAiB,OAAO,MAAM,OAAO,OAAO,OAAO,YAAY;IAC/D,mBAAmB,QAAQ,OAAO,IAAI;IACtC,+BAA+B,MAAM;IACrC,OAAO;GACT;GACA,KAAK,cAAc;IACjB,MAAM,SAAS,OAAO,YAAY;IAClC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,0DAAwD;IAG1E,MAAM,aAAa,GAAG;IACtB,MAAM,EAAE,WAAW,MAAM,WAAW,KAAK,OAAO,QAAQ,MAAM;IAC9D,MAAM,aAAa,OAAO,QAAQ,QAAQ,OAAO;IACjD,MAAM,WAAW,OAAO,QAAQ,YAAY;IAE5C,IAAI,OAAO,QAAQ,UAAU,eAAe,OAAO,cACjD,MAAM,IAAI,MACR,0FACF;IAGF,IAAI,OAAO,QAAQ,UAAU,aAAa,eACxC,MAAM,IAAI,MACR,2FACF;IAGF,IAAI,aAAa,iBAAiB,eAAe,OAAO,cACtD,MAAM,IAAI,MACR,QAAQ,SAAS,+DACnB;IAGF,MAAM,cAAmC;KACvC,GAAG,iBAAiB,OAAO,OAAO;KAClC,kBAAkB,aAAa;KAC/B,SAAS,CAAC,MAAM;IAClB;IAkBA,MAAM,EAAE,QAAQ,oBAjBI,OAAO,QAAQ,SAC/B;KACE,QAAQ,MAAM,uBAAuB,QAAQ,WAAW;KACxD,iBAAiB,CAAC;IACpB,IACA,MAAM,4BACJ,QACA,OAAO,iBAAiB;KACtB,MAAM,kBAAkB,MAAM,eAAe,cAAc,QAAQ;MACjE;MACA;KACF,CAAC;KAED,OAAO;MAAE,QAAA,MADY,uBAAuB,cAAc,WAAW;MACpD;KAAgB;IACnC,IACC,EAAE,aAAa,8BAA8B,MAAM,MAAM,KAAA,CAC5D;IAEJ,QAAQ,IACN,KAAK,UACH;KACE,QAAQ,OAAO,KAAK;KACpB;KACA;KACA,SAAS,OAAO,KAAK;KACrB;KACA,GAAI,OAAO,UAAU,KAAA,IACjB,CAAC,IACD;MACE,eAAe,OAAO;MACtB,sBAAsB,OAAO;KAC/B;KACJ;KACA,QAAQ,8BAA8B,MAAM,MAAM,KAAA,IAAY,OAAO;IACvE,GACA,MACA,CACF,CACF;IACA,+BAA+B,MAAM;IACrC,OAAO;GACT;GACA,KAAK,mBAAmB;IACtB,MAAM,SAAS,OAAO,YAAY;IAClC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,+DAA6D;IAG/E,IAAI,CAAC,OAAO,QAAQ,MAClB,MAAM,IAAI,MAAM,2DAAyD;IAG3E,MAAM,aAAa,GAAG;IACtB,MAAM,EAAE,WAAW,MAAM,WAAW,KAAK,OAAO,QAAQ,MAAM;IAC9D,MAAM,kBAAkB,MAAM,eAAe,QAAQ,QAAQ;KAC3D,YAAY,OAAO,QAAQ;KAC3B,UAAU,OAAO,QAAQ,YAAY;IACvC,CAAC;IACD,QAAQ,IACN,KAAK,UACH;KACE,YAAY,OAAO,QAAQ;KAC3B;KACA;KACA,UAAU,OAAO,QAAQ,YAAY;KACrC,QAAQ;IACV,GACA,MACA,CACF,CACF;IACA,OAAO;GACT;GACA,KAAK,SAAS;IACZ,MAAM,aAAa,GAAG;IACtB,MAAM,EAAE,WAAW,MAAM,WAAW,KAAK,OAAO,QAAQ,MAAM;IAC9D,MAAM,SAAS,MAAM,0BAA0B;KAC7C,UAAU,OAAO;KACjB,mBAAmB,OAAO,QAAQ,qBAAqB;KACvD,cAAc,OAAO;KACrB,eAAe,OAAO;IACxB,CAAC;IAED,IAAI,CAAC,OAAO,QAAQ,QAClB,MAAM,OAAO,MAAM,KAAK,OAAO,KAAK;IAGtC,QAAQ,IACN,KAAK,UACH;KACE,SAAS,OAAO;KAChB,QAAQ,OAAO,QAAQ,WAAW;KAClC,mBAAmB,OAAO;KAC1B,QAAQ;KACR,cAAc,OAAO;IACvB,GACA,MACA,CACF,CACF;IACA,OAAO;GACT;GACA,SACE,MAAM,IAAI,MAAM,oBAAoB,OAAO,QAAQ,GAAG;EAC1D;CACF,SAAS,OAAO;EACd,QAAQ,MACN,iBAAiB,QAAQ,MAAM,UAAU,2BAA2B,OAAO,KAAK,GAClF;EACA,OAAO;CACT;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-translate/cli",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Command-line interface for ai-translate: validate, check, audit, and sync localized content generated from a single source locale.",
5
5
  "keywords": [
6
6
  "i18n",
@@ -46,9 +46,14 @@
46
46
  "dependencies": {
47
47
  "dotenv": "17.4.2",
48
48
  "jiti": "2.7.0",
49
- "@ai-translate/core": "0.3.2",
50
- "@ai-translate/fs-json": "0.2.3",
51
- "@ai-translate/next": "0.1.1"
49
+ "@ai-translate/apple": "0.1.0",
50
+ "@ai-translate/core": "0.4.0",
51
+ "@ai-translate/fs-json": "0.2.4",
52
+ "@ai-translate/integrations": "0.1.0",
53
+ "@ai-translate/next": "0.1.2"
54
+ },
55
+ "devDependencies": {
56
+ "@ai-translate/message-formats": "0.3.0"
52
57
  },
53
58
  "engines": {
54
59
  "node": ">=20.19.0"
@@ -1 +0,0 @@
1
- {"version":3,"file":"src-Cnnq284f.mjs","names":["fs","parseDotenv","fs","fs"],"sources":["../src/config.ts","../src/init.ts","../src/transaction.ts","../src/index.ts"],"sourcesContent":["import { existsSync, promises as fs } from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { config as loadDotenv, parse as parseDotenv } from \"dotenv\";\nimport { createJiti } from \"jiti\";\n\nimport { defineConfig } from \"@ai-translate/core\";\nimport type { AiTranslateConfig } from \"@ai-translate/core/types\";\n\nconst CONFIG_CANDIDATES = [\n \"ai-translate.config.ts\",\n \"ai-translate.config.mts\",\n \"ai-translate.config.js\",\n \"ai-translate.config.mjs\",\n] as const;\n\nfunction isAiTranslateConfig(value: unknown): value is AiTranslateConfig {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"catalogs\" in value &&\n \"provider\" in value &&\n \"sourceLocale\" in value &&\n \"state\" in value &&\n \"targetLocales\" in value\n );\n}\n\nexport function findConfigPath(cwd: string, explicitPath?: string): string {\n if (explicitPath) {\n return path.resolve(cwd, explicitPath);\n }\n\n for (const candidate of CONFIG_CANDIDATES) {\n const fullPath = path.join(cwd, candidate);\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n throw new Error(\n `Unable to find ai-translate config in ${cwd}. Expected one of: ${CONFIG_CANDIDATES.join(\", \")}`,\n );\n}\n\nexport async function loadEnvFiles(cwd: string): Promise<Record<string, string>> {\n const nodeEnv = process.env.NODE_ENV;\n const candidates = [\n \".env\",\n \".env.local\",\n nodeEnv ? `.env.${nodeEnv}` : undefined,\n nodeEnv ? `.env.${nodeEnv}.local` : undefined,\n ].filter((value): value is string => value !== undefined);\n\n const merged: Record<string, string> = {};\n for (const fileName of candidates) {\n const filePath = path.join(cwd, fileName);\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n Object.assign(merged, parseDotenv(raw));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n }\n\n loadDotenv({\n override: false,\n path: candidates.map((candidate) => path.join(cwd, candidate)),\n processEnv: process.env,\n });\n\n return merged;\n}\n\nexport async function loadConfig(\n cwd: string,\n explicitPath?: string,\n): Promise<{ config: AiTranslateConfig; configPath: string }> {\n const configPath = findConfigPath(cwd, explicitPath);\n const jiti = createJiti(import.meta.url, {\n interopDefault: true,\n moduleCache: false,\n });\n const loaded: unknown = await jiti.import(configPath);\n const resolved =\n typeof loaded === \"object\" && loaded !== null && \"default\" in loaded\n ? loaded.default ?? loaded\n : loaded;\n\n if (!isAiTranslateConfig(resolved)) {\n throw new Error(`Config file ${configPath} did not export an ai-translate config object.`);\n }\n\n return {\n config: defineConfig(resolved),\n configPath,\n };\n}\n","import { promises as fs } from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { detectProject, renderConfig } from \"@ai-translate/next\";\nimport type { DetectedSetup, Integration, ProviderChoice } from \"@ai-translate/next\";\n\nconst CONFIG_FILENAME = \"ai-translate.config.ts\";\nconst DEFAULT_AI_SDK_PACKAGE = \"@ai-sdk/openai\";\n\n/** Packages a generated config imports from, whichever provider it wires up. */\nconst REQUIRED_PACKAGES = [\"@ai-translate/cli\", \"@ai-translate/fs-json\"];\n\nexport interface InitOptions {\n /** Overwrites an existing config instead of refusing. */\n force?: boolean;\n /** Selects an integration when detection finds more than one. */\n integration?: string;\n /** Replaces the shipped integrations. A project that localizes something the\n * toolkit does not recognise can register its own detector rather than\n * writing the config by hand. */\n integrations?: readonly Integration[];\n /** Model id written into the generated config. */\n model?: string;\n /** Prints the config that would be written and touches nothing. */\n preview?: boolean;\n /** `openai` talks to OpenAI directly; `ai-sdk` routes through the AI SDK. */\n provider?: ProviderChoice;\n /** AI SDK vendor package, for example `@ai-sdk/anthropic`. */\n providerPackage?: string;\n}\n\nexport interface InitResult {\n configPath: string | null;\n lines: readonly string[];\n setup: DetectedSetup;\n}\n\nfunction describe(setup: DetectedSetup): string[] {\n return [\n `Detected ${setup.displayName}:`,\n ...setup.evidence.map((item) => ` - ${item.detail} (${item.source})`),\n ` - Source locale ${setup.plan.sourceLocale}, ${String(\n setup.plan.targetLocales.length,\n )} target locale(s): ${setup.plan.targetLocales.join(\", \")}`,\n ];\n}\n\nasync function missingPackages(\n cwd: string,\n plan: DetectedSetup[\"plan\"],\n options: InitOptions,\n): Promise<string[]> {\n const expected = [\n ...REQUIRED_PACKAGES,\n ...(plan.messageFormat === \"plain\" ? [] : [\"@ai-translate/message-formats\"]),\n ...(options.provider === \"ai-sdk\"\n ? [\"@ai-translate/provider-ai-sdk\", \"ai\", options.providerPackage ?? DEFAULT_AI_SDK_PACKAGE]\n : [\"@ai-translate/provider-openai\"]),\n ];\n\n try {\n const raw = await fs.readFile(path.join(cwd, \"package.json\"), \"utf8\");\n const manifest = JSON.parse(raw) as Record<string, Record<string, string> | undefined>;\n const declared = new Set([\n ...Object.keys(manifest.dependencies ?? {}),\n ...Object.keys(manifest.devDependencies ?? {}),\n ]);\n return expected.filter((name) => !declared.has(name));\n } catch {\n return expected;\n }\n}\n\nfunction chooseSetup(\n setups: readonly DetectedSetup[],\n requested: string | undefined,\n): DetectedSetup {\n if (requested !== undefined) {\n const match = setups.find((setup) => setup.integrationId === requested);\n if (match === undefined) {\n throw new Error(\n `No ${requested} setup was detected. Detected: ${\n setups.map((setup) => setup.integrationId).join(\", \") || \"none\"\n }.`,\n );\n }\n return match;\n }\n\n const [best, ...rest] = setups;\n if (best === undefined) {\n throw new Error(\n \"No supported Next.js localization setup was found. ai-translate init currently \" +\n \"recognises next-intl and i18next. Write ai-translate.config.ts by hand, or run \" +\n \"init from the directory holding package.json and your locale files.\",\n );\n }\n if (rest.length > 0 && rest[0]?.confidence === best.confidence) {\n // Two equally plausible setups is a genuine ambiguity, not something to\n // resolve by coin flip: writing the wrong one silently would point the\n // whole pipeline at the wrong catalog.\n throw new Error(\n `Found more than one localization setup (${setups\n .map((setup) => setup.integrationId)\n .join(\", \")}). Re-run with --integration <id> to choose.`,\n );\n }\n return best;\n}\n\n/**\n * Detects the project's localization setup and writes a config for it.\n *\n * Nothing else is touched. Installing packages, wiring scripts, and editing the\n * Next.js config stay in the user's hands, so `init` on an unfamiliar repository\n * produces exactly one new file and a list of instructions.\n */\nexport async function runInit(cwd: string, options: InitOptions = {}): Promise<InitResult> {\n const setups = await detectProject(\n cwd,\n options.integrations === undefined ? {} : { integrations: options.integrations },\n );\n const setup = chooseSetup(setups, options.integration);\n const contents = renderConfig(setup.plan, {\n ...(options.model === undefined ? {} : { model: options.model }),\n ...(options.provider === undefined ? {} : { provider: options.provider }),\n ...(options.providerPackage === undefined ? {} : { providerPackage: options.providerPackage }),\n });\n const configPath = path.join(cwd, CONFIG_FILENAME);\n const lines = describe(setup);\n\n for (const warning of setup.plan.warnings) {\n lines.push(` ! ${warning}`);\n }\n\n const others = setups.filter((candidate) => candidate !== setup);\n if (others.length > 0) {\n lines.push(\n `Also detected, not used: ${others.map((candidate) => candidate.displayName).join(\", \")}.`,\n );\n }\n\n if (options.preview === true) {\n lines.push(\"\", `Would write ${CONFIG_FILENAME}:`, \"\", contents);\n return { configPath: null, lines, setup };\n }\n\n const exists = await fs\n .access(configPath)\n .then(() => true)\n .catch(() => false);\n if (exists && options.force !== true) {\n throw new Error(`${CONFIG_FILENAME} already exists. Pass --force to overwrite it.`);\n }\n\n await fs.writeFile(configPath, contents, \"utf8\");\n lines.push(\"\", `Wrote ${CONFIG_FILENAME}.`, \"\", \"Next steps:\");\n\n const install = await missingPackages(cwd, setup.plan, options);\n let step = 1;\n if (install.length > 0) {\n lines.push(` ${String(step++)}. Install: ${install.join(\" \")}`);\n }\n const apiKeyVariable =\n options.provider === \"ai-sdk\"\n ? `the API key your ${options.providerPackage ?? DEFAULT_AI_SDK_PACKAGE} provider reads`\n : \"OPENAI_API_KEY\";\n lines.push(\n ` ${String(step++)}. Set ${apiKeyVariable}, in your shell or in .env.local.`,\n ` ${String(step++)}. Review the model and locale list in ${CONFIG_FILENAME}.`,\n ` ${String(step++)}. Run \"ai-translate validate\" to confirm the config loads.`,\n ` ${String(step++)}. Run \"ai-translate check\" to see what a sync would do.`,\n ` ${String(step)}. Run \"ai-translate sync\" to translate.`,\n );\n\n return { configPath, lines, setup };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\n\nimport type {\n AiTranslateConfig,\n CatalogAdapter,\n DocumentRef,\n Entry,\n LoadedDocument,\n ScaffoldLocaleOptions,\n ScaffoldLocaleResult,\n SyncStateLoadScope,\n SyncStateSnapshot,\n SyncStateStore,\n} from \"@ai-translate/core/types\";\nimport { supportsScopedSave } from \"@ai-translate/core/types\";\nimport type {\n DurableDocumentChange,\n} from \"@ai-translate/fs-json\";\n\nconst DURABLE_TRANSACTION_STATE_STORE = Symbol.for(\n \"@ai-translate/fs-json/durable-transaction-state-store\",\n);\n\nfunction cloneState(state: SyncStateSnapshot): SyncStateSnapshot {\n return structuredClone(state);\n}\n\nfunction cloneEntry(entry: Entry): Entry {\n return {\n ...entry,\n address: entry.address.map((segment) => ({ ...segment })),\n ...(entry.meta === undefined ? {} : { meta: { ...entry.meta } }),\n ...(entry.tokens === undefined ? {} : { tokens: entry.tokens.map((token) => ({ ...token })) }),\n };\n}\n\n/** Adapter state may contain parser-owned class instances, so retain it while\n * isolating the mutable translation entries. Staged writes are subsequently\n * serialized and reloaded by the real adapter to obtain isolated live state. */\nfunction cloneDocument(document: LoadedDocument): LoadedDocument {\n return {\n entries: document.entries.map(cloneEntry),\n ...(document.reconciliation === undefined\n ? {}\n : {\n reconciliation: {\n ...(document.reconciliation.previousPointers === undefined\n ? {}\n : { previousPointers: { ...document.reconciliation.previousPointers } }),\n ...(document.reconciliation.retiredStateKeys === undefined\n ? {}\n : { retiredStateKeys: [...document.reconciliation.retiredStateKeys] }),\n },\n }),\n ref: { ...document.ref },\n state: document.state,\n ...(document.structureDigest === undefined\n ? {}\n : { structureDigest: document.structureDigest }),\n };\n}\n\nfunction restoreDocumentRef(document: LoadedDocument, ref: DocumentRef): LoadedDocument {\n return cloneDocument({ ...document, ref: { ...ref } });\n}\n\nfunction documentKey(ref: DocumentRef): string {\n return [ref.catalogId, ref.format, ref.locale, ref.path, ref.unitId].join(\"\\u0000\");\n}\n\nclass StagedStateStore implements SyncStateStore {\n private dirty = false;\n private snapshot: SyncStateSnapshot;\n\n constructor(initial: SyncStateSnapshot) {\n this.snapshot = cloneState(initial);\n }\n\n hasChanges(): boolean {\n return this.dirty;\n }\n\n load(): Promise<SyncStateSnapshot> {\n return Promise.resolve(cloneState(this.snapshot));\n }\n\n save(state: SyncStateSnapshot): Promise<void> {\n this.snapshot = cloneState(state);\n this.dirty = true;\n return Promise.resolve();\n }\n\n stagedSnapshot(): SyncStateSnapshot {\n return cloneState(this.snapshot);\n }\n\n withLock<T>(operation: () => Promise<T>): Promise<T> {\n return operation();\n }\n}\n\ninterface StagedFile {\n mode: number | undefined;\n original: Buffer | null;\n realPath: string;\n tempPath: string;\n}\n\nasync function readOriginal(filePath: string): Promise<{\n mode: number | undefined;\n original: Buffer | null;\n}> {\n try {\n const [original, stats] = await Promise.all([fs.readFile(filePath), fs.stat(filePath)]);\n return { mode: stats.mode, original };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { mode: undefined, original: null };\n }\n throw error;\n }\n}\n\nasync function writeFileAtomic(filePath: string, contents: Buffer, mode?: number): Promise<void> {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n const temporaryPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.ai-translate-${randomUUID()}`,\n );\n try {\n await fs.writeFile(temporaryPath, contents);\n if (mode !== undefined) {\n await fs.chmod(temporaryPath, mode);\n }\n await fs.rename(temporaryPath, filePath);\n } finally {\n await fs.rm(temporaryPath, { force: true });\n }\n}\n\nclass StagedCatalogs {\n private readonly files = new Map<string, StagedFile>();\n private readonly pendingRefs = new Map<string, { catalog: CatalogAdapter; ref: DocumentRef }>();\n private tempRoot: string | undefined;\n\n constructor(\n private readonly catalogs: readonly CatalogAdapter[],\n private readonly sourceLocale: string,\n ) {}\n\n adapters(): readonly CatalogAdapter[] {\n return this.catalogs.map((catalog) => this.createAdapter(catalog));\n }\n\n async cleanup(): Promise<void> {\n if (this.tempRoot !== undefined) {\n await fs.rm(this.tempRoot, { force: true, recursive: true });\n }\n }\n\n async promote(): Promise<void> {\n for (const staged of this.files.values()) {\n await writeFileAtomic(staged.realPath, await fs.readFile(staged.tempPath), staged.mode);\n }\n }\n\n async durableChanges(): Promise<readonly DurableDocumentChange[]> {\n return Promise.all(\n [...this.files.values()].map(async (staged) => ({\n ...(staged.mode === undefined ? {} : { mode: staged.mode }),\n next: await fs.readFile(staged.tempPath),\n original: staged.original,\n path: staged.realPath,\n })),\n );\n }\n\n async rollback(): Promise<void> {\n const failures: unknown[] = [];\n for (const staged of this.files.values()) {\n try {\n if (staged.original === null) {\n await fs.rm(staged.realPath, { force: true });\n } else {\n await writeFileAtomic(staged.realPath, staged.original, staged.mode);\n }\n } catch (error) {\n failures.push(error);\n }\n }\n if (failures.length > 0) {\n throw new AggregateError(failures, \"Failed to restore localized documents after commit.\");\n }\n }\n\n private async stageFile(realPath: string): Promise<StagedFile> {\n const existing = this.files.get(realPath);\n if (existing) {\n return existing;\n }\n this.tempRoot ??= await fs.mkdtemp(path.join(os.tmpdir(), \"ai-translate-stage-\"));\n const { mode, original } = await readOriginal(realPath);\n const tempPath = path.join(\n this.tempRoot,\n `${String(this.files.size)}${path.extname(realPath) || \".document\"}`,\n );\n if (original !== null) {\n await fs.writeFile(tempPath, original);\n }\n const staged = { mode, original, realPath, tempPath };\n this.files.set(realPath, staged);\n return staged;\n }\n\n private async loadStaged(\n catalog: CatalogAdapter,\n ref: DocumentRef,\n ): Promise<LoadedDocument | null> {\n const staged = this.files.get(ref.path);\n if (!staged) {\n const document = await catalog.loadDocument(ref);\n return document === null ? null : cloneDocument(document);\n }\n const tempRef = { ...ref, path: staged.tempPath };\n const document = await catalog.loadDocument(tempRef);\n return document === null ? null : restoreDocumentRef(document, ref);\n }\n\n private async writeStaged(catalog: CatalogAdapter, document: LoadedDocument): Promise<void> {\n const staged = await this.stageFile(document.ref.path);\n const tempRef = { ...document.ref, path: staged.tempPath };\n const stagedDocument = await catalog.loadDocument(tempRef);\n await catalog.writeDocument({\n ...cloneDocument(document),\n ref: tempRef,\n // The reconciled document is authoritative: it carries the source shape,\n // so keys dropped from the source do not survive in the target. Formats\n // that pack several logical documents into one file merge that shape\n // into the staged file themselves so sibling writes are not lost.\n state:\n stagedDocument === null || catalog.mergeStagedState === undefined\n ? document.state\n : catalog.mergeStagedState({ document, staged: stagedDocument }),\n });\n const persisted = await catalog.loadDocument(tempRef);\n if (persisted === null) {\n throw new Error(\n `Catalog \"${catalog.id}\" did not persist staged document ${document.ref.path}.`,\n );\n }\n this.pendingRefs.set(documentKey(document.ref), { catalog, ref: { ...document.ref } });\n\n // A bundle catalog can expose several logical documents backed by one file.\n // Re-read every staged ref for the path so later repair rounds see the\n // aggregate serialized state, not a pre-write per-unit snapshot.\n for (const pending of this.pendingRefs.values()) {\n if (pending.ref.path === document.ref.path) {\n const pendingTempRef = { ...pending.ref, path: staged.tempPath };\n if ((await pending.catalog.loadDocument(pendingTempRef)) === null) {\n throw new Error(\n `Catalog \"${pending.catalog.id}\" could not reload staged document ${pending.ref.path}.`,\n );\n }\n }\n }\n }\n\n private createAdapter(catalog: CatalogAdapter): CatalogAdapter {\n const mergeStagedState = catalog.mergeStagedState?.bind(catalog);\n return {\n createDocumentRef: (sourceRef, locale) => catalog.createDocumentRef(sourceRef, locale),\n id: catalog.id,\n listDocumentRefs: (sourceLocale) => catalog.listDocumentRefs(sourceLocale),\n loadDocument: (ref) => this.loadStaged(catalog, ref),\n ...(mergeStagedState === undefined ? {} : { mergeStagedState }),\n reconcileDocument: async (args) => {\n const document = await catalog.reconcileDocument({\n ...(args.history === undefined\n ? {}\n : { history: args.history.map((entry) => structuredClone(entry)) }),\n ref: { ...args.ref },\n source: cloneDocument(args.source),\n target: args.target === null ? null : cloneDocument(args.target),\n });\n return cloneDocument(document);\n },\n ...(catalog.scaffoldLocale === undefined\n ? {}\n : {\n scaffoldLocale: (options: ScaffoldLocaleOptions) =>\n this.scaffoldCatalog(catalog, options),\n }),\n writeDocument: (document) => this.writeStaged(catalog, document),\n };\n }\n\n private async scaffoldCatalog(\n catalog: CatalogAdapter,\n options: ScaffoldLocaleOptions,\n ): Promise<ScaffoldLocaleResult> {\n const strategy = options.strategy ?? \"copy-source\";\n const fromLocale =\n strategy === \"copy-source\" ? this.sourceLocale : (options.fromLocale ?? this.sourceLocale);\n const refs = await catalog.listDocumentRefs(fromLocale);\n if (strategy === \"empty\") {\n return {\n catalogId: catalog.id,\n createdDocuments: 0,\n locale: options.locale,\n skippedDocuments: refs.length,\n strategy,\n };\n }\n\n let createdDocuments = 0;\n let skippedDocuments = 0;\n const adapter = this.createAdapter(catalog);\n for (const sourceRef of refs) {\n const targetRef = adapter.createDocumentRef(sourceRef, options.locale);\n if ((await adapter.loadDocument(targetRef)) !== null) {\n skippedDocuments += 1;\n continue;\n }\n const source = await adapter.loadDocument(sourceRef);\n if (source === null) {\n skippedDocuments += 1;\n continue;\n }\n await adapter.writeDocument(\n await adapter.reconcileDocument({ ref: targetRef, source, target: null }),\n );\n createdDocuments += 1;\n }\n\n return {\n catalogId: catalog.id,\n createdDocuments,\n locale: options.locale,\n skippedDocuments,\n strategy,\n };\n }\n}\n\nfunction commitFailure(commitError: unknown, rollbackErrors: readonly unknown[]): Error {\n return rollbackErrors.length === 0\n ? commitError instanceof Error\n ? commitError\n : new Error(String(commitError))\n : new AggregateError(\n [commitError, ...rollbackErrors],\n \"Translation commit failed and could not be completely rolled back.\",\n );\n}\n\ninterface DurableCommitCoordinator {\n commit(transaction: {\n documents: readonly DurableDocumentChange[];\n initialState: SyncStateSnapshot;\n nextState: SyncStateSnapshot;\n }): Promise<void>;\n}\n\nfunction durableStateStore(state: SyncStateStore): DurableCommitCoordinator | null {\n if (typeof state === \"object\" && state !== null) {\n const candidate = (state as unknown as Record<PropertyKey, unknown>)[\n DURABLE_TRANSACTION_STATE_STORE\n ];\n if (\n typeof candidate === \"object\" &&\n candidate !== null &&\n \"commit\" in candidate &&\n typeof candidate.commit === \"function\"\n ) {\n return candidate as DurableCommitCoordinator;\n }\n }\n return null;\n}\n\nexport async function runStagedCatalogTransaction<T>(\n config: AiTranslateConfig,\n operation: (stagedConfig: AiTranslateConfig) => Promise<T>,\n shouldCommit: (result: T) => boolean = () => true,\n scope?: SyncStateLoadScope,\n): Promise<T> {\n /*\n * Staging copies the snapshot several times between here and the commit, so\n * loading locales the run cannot touch is the dominant cost of a narrow sync.\n * The scope is only honoured by stores that merge on save; everywhere else the\n * snapshot still has to describe the whole corpus, because omission means\n * deletion.\n */\n const saveScope = supportsScopedSave(config.state) ? scope : undefined;\n\n return config.state.withLock(async () => {\n const initialState = await config.state.load(saveScope);\n const stagedState = new StagedStateStore(initialState);\n const stagedCatalogs = new StagedCatalogs(config.catalogs, config.sourceLocale);\n const stagedConfig: AiTranslateConfig = {\n ...config,\n catalogs: stagedCatalogs.adapters(),\n state: stagedState,\n };\n try {\n const result = await operation(stagedConfig);\n if (!shouldCommit(result)) {\n return result;\n }\n\n const durableStore = durableStateStore(config.state);\n if (durableStore !== null) {\n const documents = await stagedCatalogs.durableChanges();\n if (documents.length > 0 || stagedState.hasChanges()) {\n await durableStore.commit({\n documents,\n initialState: cloneState(initialState),\n nextState: stagedState.stagedSnapshot(),\n ...(saveScope === undefined ? {} : { scope: saveScope }),\n });\n }\n } else {\n let stateSaveAttempted = false;\n try {\n await stagedCatalogs.promote();\n if (stagedState.hasChanges()) {\n stateSaveAttempted = true;\n await config.state.save(stagedState.stagedSnapshot(), saveScope);\n }\n } catch (error) {\n const rollbackErrors: unknown[] = [];\n try {\n await stagedCatalogs.rollback();\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n if (stateSaveAttempted) {\n try {\n await config.state.save(cloneState(initialState), saveScope);\n } catch (rollbackError) {\n rollbackErrors.push(rollbackError);\n }\n }\n throw commitFailure(error, rollbackErrors);\n }\n }\n return result;\n } finally {\n await stagedCatalogs.cleanup();\n }\n });\n}\n","import {\n auditCatalogs,\n resolveStateScope,\n syncCatalogs,\n usesGeneratorSelfCheck,\n validateCatalogs,\n withTranslationIssueCache,\n} from \"@ai-translate/core\";\nimport type {\n AiTranslateConfig,\n CatalogScaffoldStrategy,\n SemanticAuditResult,\n SyncCatalogsOptions,\n SyncResult,\n SyncStateSnapshot,\n ValidationResult,\n} from \"@ai-translate/core/types\";\nimport { adoptExistingTranslations } from \"@ai-translate/fs-json\";\nimport type { IdenticalToSourcePolicy } from \"@ai-translate/fs-json\";\nimport type { ProviderChoice } from \"@ai-translate/next\";\n\nimport { loadConfig, loadEnvFiles } from \"./config\";\nimport { runInit } from \"./init\";\nimport { runStagedCatalogTransaction } from \"./transaction\";\n\nexport { defineConfig } from \"@ai-translate/core\";\nexport { findConfigPath, loadConfig, loadEnvFiles } from \"./config\";\n\ninterface CommandOptions {\n auditCheck?: boolean;\n catalogIds?: string[];\n config?: string;\n dryRun?: boolean;\n force?: boolean;\n forceRetranslate?: boolean;\n forceRetranslatePaths?: string[];\n includePaths?: string[];\n from?: string;\n identicalToSource?: IdenticalToSourcePolicy;\n locales?: string[];\n integration?: string;\n maxPendingTranslations?: number;\n model?: string;\n preview?: boolean;\n provider?: string;\n providerPackage?: string;\n refresh?: boolean;\n strategy?: CatalogScaffoldStrategy;\n unitIds?: string[];\n}\n\ninterface ParsedCommand {\n command?: string;\n options: CommandOptions;\n positionals: string[];\n}\n\nfunction requireOptionValue(optionName: string, value: string | undefined): string {\n if (value === undefined) {\n throw new Error(`Option \"--${optionName}\" requires a value.`);\n }\n\n return value;\n}\n\nfunction requireProviderChoice(value: string): ProviderChoice {\n if (value !== \"ai-sdk\" && value !== \"openai\") {\n throw new Error(`Option \"--provider\" accepts \"openai\" or \"ai-sdk\", not \"${value}\".`);\n }\n\n return value;\n}\n\nfunction requireIdenticalToSourcePolicy(value: string): IdenticalToSourcePolicy {\n if (value !== \"adopt\" && value !== \"skip\") {\n throw new Error(\n `Option \"--identical-to-source\" accepts \"adopt\" or \"skip\", not \"${value}\".`,\n );\n }\n\n return value;\n}\n\nfunction requireNonNegativeIntegerOption(optionName: string, value: string | undefined): number {\n const rawValue = requireOptionValue(optionName, value);\n const parsedValue = Number(rawValue);\n if (!Number.isSafeInteger(parsedValue) || parsedValue < 0) {\n throw new Error(`Option \"--${optionName}\" requires a non-negative integer.`);\n }\n return parsedValue;\n}\n\nasync function validateConfig(\n config: AiTranslateConfig,\n configPath: string,\n options: SyncCatalogsOptions,\n): Promise<ValidationResult> {\n const result = await validateCatalogs(config, options);\n return {\n ...result,\n configPath,\n };\n}\n\nconst DEFAULT_SEMANTIC_REPAIR_ROUNDS = 0;\n\ninterface SemanticAuditConvergenceResult {\n audit: SemanticAuditResult | undefined;\n repairRounds: number;\n sync: SyncResult;\n}\n\nfunction printSyncSummary(\n result: SyncResult,\n semanticAudit?: SemanticAuditResult,\n semanticRepairRounds = 0,\n): void {\n const pendingTranslationReasons = summarizePendingTranslationReasons(result);\n const failedTranslationIssues = summarizeFailedTranslationIssues(result);\n console.log(\n JSON.stringify(\n {\n dryRun: result.dryRun,\n metrics: result.metrics,\n ...(result.dryRun && Object.keys(pendingTranslationReasons).length > 0\n ? { pendingTranslationReasons }\n : {}),\n ...(semanticAudit === undefined ? {} : { semanticAudit, semanticRepairRounds }),\n ...(failedTranslationIssues === undefined ? {} : { failedTranslationIssues }),\n },\n null,\n 2,\n ),\n );\n}\n\nfunction summarizeFailedTranslationIssues(result: SyncResult):\n | {\n counts: Record<string, number>;\n examples: readonly {\n catalogId: string;\n code: string;\n locale: string;\n message: string;\n path: string;\n unitId: string;\n }[];\n }\n | undefined {\n if (result.metrics.failedEntries === 0) {\n return undefined;\n }\n const errors = result.documents.flatMap((document) =>\n document.issues\n .filter((issue) => issue.severity === \"error\")\n .map((issue) => ({\n catalogId: document.catalogId,\n code: issue.code,\n locale: document.locale,\n message: issue.message,\n path: document.path,\n unitId: document.unitId,\n })),\n );\n const counts: Record<string, number> = {};\n for (const issue of errors) {\n counts[issue.code] = (counts[issue.code] ?? 0) + 1;\n }\n return {\n counts: Object.fromEntries(\n Object.entries(counts).toSorted(\n ([leftCode, leftCount], [rightCode, rightCount]) =>\n rightCount - leftCount || leftCode.localeCompare(rightCode),\n ),\n ),\n examples: errors.slice(0, 25),\n };\n}\n\nfunction summarizePendingTranslationReasons(result: SyncResult): Record<string, number> {\n const summary: Record<string, number> = {};\n for (const document of result.documents) {\n for (const [reason, count] of Object.entries(document.pendingTranslationReasons ?? {})) {\n summary[reason] = (summary[reason] ?? 0) + count;\n }\n }\n return Object.fromEntries(\n Object.entries(summary).toSorted(\n ([leftReason, leftCount], [rightReason, rightCount]) =>\n rightCount - leftCount || leftReason.localeCompare(rightReason),\n ),\n );\n}\n\nfunction dryRunBudgetError(config: AiTranslateConfig, result: SyncResult): string | undefined {\n if (!result.dryRun || config.validation?.dryRunBudget === undefined) {\n return undefined;\n }\n const budget = config.validation.dryRunBudget;\n if (\n budget.maxPendingTranslations !== undefined &&\n result.metrics.translatedEntries > budget.maxPendingTranslations\n ) {\n return (\n `Translation dry-run planned ${String(\n result.metrics.translatedEntries,\n )} provider translations, ` +\n `exceeding the configured budget of ${String(budget.maxPendingTranslations)}.`\n );\n }\n const reasons = summarizePendingTranslationReasons(result);\n const forbidden = (budget.forbiddenPendingTranslationReasons ?? []).filter(\n (reason) => (reasons[reason] ?? 0) > 0,\n );\n return forbidden.length === 0\n ? undefined\n : `Translation dry-run included forbidden selection reasons: ${forbidden\n .map((reason) => `${reason} (${String(reasons[reason] ?? 0)})`)\n .join(\", \")}.`;\n}\n\nfunction assertDryRunBudget(config: AiTranslateConfig, result: SyncResult): void {\n const error = dryRunBudgetError(config, result);\n if (error !== undefined) {\n throw new Error(error);\n }\n}\n\nasync function convergeSemanticAudits(\n config: AiTranslateConfig,\n options: SyncCatalogsOptions,\n): Promise<SemanticAuditConvergenceResult> {\n let sync = await syncCatalogs(config, options);\n if (\n options.dryRun === true ||\n sync.metrics.failedEntries > 0 ||\n (config.semanticAudits?.length ?? 0) === 0 ||\n usesGeneratorSelfCheck(config)\n ) {\n return { audit: undefined, repairRounds: 0, sync };\n }\n\n let audit = await auditCatalogs(config, options);\n let repairRounds = 0;\n const maxSemanticRepairRounds =\n config.validation?.semanticRepairAttempts ?? DEFAULT_SEMANTIC_REPAIR_ROUNDS;\n const repairOptions = { ...options };\n delete repairOptions.forceRetranslate;\n delete repairOptions.forceRetranslatePaths;\n while (audit.retranslate > 0 && repairRounds < maxSemanticRepairRounds) {\n repairRounds += 1;\n sync = await syncCatalogs(config, repairOptions);\n if (sync.metrics.failedEntries > 0) {\n break;\n }\n audit = await auditCatalogs(config, options);\n }\n\n return { audit, repairRounds, sync };\n}\n\nasync function syncWithSemanticAuditConvergence(\n config: AiTranslateConfig,\n options: SyncCatalogsOptions,\n): Promise<SemanticAuditConvergenceResult> {\n if (options.dryRun === true) {\n return convergeSemanticAudits(config, options);\n }\n return runStagedCatalogTransaction(\n config,\n (stagedConfig) => convergeSemanticAudits(stagedConfig, options),\n (result) => semanticAuditConvergenceError(result) === undefined,\n resolveStateScope(config, options),\n );\n}\n\nfunction semanticAuditConvergenceError(result: SemanticAuditConvergenceResult): string | undefined {\n if (result.sync.metrics.failedEntries > 0) {\n return \"Sync completed with failed translation entries.\";\n }\n if ((result.audit?.unresolved ?? 0) > 0) {\n return \"Sync completed with unresolved semantic audits. Review or refresh the audit findings.\";\n }\n if ((result.audit?.retranslate ?? 0) > 0) {\n return `Semantic audit rejected translations after ${String(\n result.repairRounds,\n )} configured repair round(s).`;\n }\n if (result.audit?.issues.some((issue) => issue.severity === \"error\")) {\n return \"Semantic audit completed with unresolved or unsafe translations.\";\n }\n return undefined;\n}\n\nfunction assertSemanticAuditConvergence(result: SemanticAuditConvergenceResult): void {\n const error = semanticAuditConvergenceError(result);\n if (error !== undefined) {\n throw new Error(error);\n }\n}\n\nfunction buildSyncOptions(options: CommandOptions): SyncCatalogsOptions {\n const syncOptions: SyncCatalogsOptions = {};\n if (options.catalogIds && options.catalogIds.length > 0) {\n syncOptions.catalogIds = options.catalogIds;\n }\n\n if (options.dryRun !== undefined) {\n syncOptions.dryRun = options.dryRun;\n }\n\n if (options.forceRetranslate !== undefined) {\n syncOptions.forceRetranslate = options.forceRetranslate;\n }\n\n if (options.forceRetranslatePaths && options.forceRetranslatePaths.length > 0) {\n syncOptions.forceRetranslate = true;\n syncOptions.forceRetranslatePaths = options.forceRetranslatePaths;\n }\n\n if (options.includePaths && options.includePaths.length > 0) {\n syncOptions.includePaths = options.includePaths;\n }\n\n if (options.locales && options.locales.length > 0) {\n syncOptions.locales = options.locales;\n }\n\n if (options.maxPendingTranslations !== undefined) {\n syncOptions.maxPendingTranslations = options.maxPendingTranslations;\n }\n\n if (options.unitIds && options.unitIds.length > 0) {\n syncOptions.unitIds = options.unitIds;\n }\n\n return syncOptions;\n}\n\nfunction projectStateLocales(\n state: SyncStateSnapshot,\n locales: readonly string[] | undefined,\n): SyncStateSnapshot {\n if (locales === undefined || locales.length === 0) {\n return state;\n }\n const included = new Set(locales);\n return {\n entries: Object.fromEntries(\n Object.entries(state.entries).filter(([, entry]) => included.has(entry.locale)),\n ),\n version: state.version,\n };\n}\n\nfunction hasStoredSemanticAudits(state: SyncStateSnapshot): boolean {\n return Object.values(state.entries).some(\n (entry) => Object.keys(entry.validationAudits ?? {}).length > 0,\n );\n}\n\nconst EMPTY_SEMANTIC_AUDIT = {\n accepted: 0,\n audited: 0,\n cached: 0,\n checked: 0,\n issues: [],\n retranslate: 0,\n unresolved: 0,\n} as const;\n\nasync function scaffoldLocale(\n config: AiTranslateConfig,\n locale: string,\n options: {\n fromLocale?: string;\n strategy?: CatalogScaffoldStrategy;\n } = {},\n) {\n return Promise.all(\n config.catalogs.map(async (catalog) => {\n if (!catalog.scaffoldLocale) {\n return null;\n }\n\n return catalog.scaffoldLocale({\n ...(options.fromLocale === undefined ? {} : { fromLocale: options.fromLocale }),\n locale,\n ...(options.strategy === undefined ? {} : { strategy: options.strategy }),\n });\n }),\n );\n}\n\nfunction printHelp(): void {\n console.log(`ai-translate\n\nUsage:\n ai-translate init [--integration <next-intl|i18next>] [--provider <openai|ai-sdk>] [--provider-package <@ai-sdk/...>] [--model <id>] [--preview] [--force]\n ai-translate validate [--config <path>]\n ai-translate check [--config <path>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--include-path <json-pointer>] [--max-pending-translations <count>]\n ai-translate audit [--check] [--refresh] [--config <path>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--include-path <json-pointer>]\n ai-translate sync [--config <path>] [--dry-run] [--force-retranslate] [--force-retranslate-path <json-pointer>] [--include-path <json-pointer>] [--locale <locale>] [--catalog <id>] [--unit <id>] [--max-pending-translations <count>]\n ai-translate new-locale <locale> [--from <locale>] [--strategy <strategy>] [--config <path>]\n ai-translate scaffold-locale <locale> --from <locale> [--strategy <strategy>] [--config <path>]\n ai-translate adopt [--identical-to-source <adopt|skip>] [--dry-run] [--config <path>]\n ai-translate --help\n ai-translate --version`);\n}\n\nfunction parseCommand(argv: readonly string[]): ParsedCommand {\n const options: CommandOptions = {};\n const positionals: string[] = [];\n let command: string | undefined;\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (arg === undefined) {\n continue;\n }\n\n if (arg === \"--help\" || arg === \"-h\") {\n return {\n command: \"help\",\n options,\n positionals,\n };\n }\n\n if (arg === \"--version\" || arg === \"-v\") {\n return {\n command: \"version\",\n options,\n positionals,\n };\n }\n\n if (arg.startsWith(\"--\")) {\n const [flag = \"\", inlineValue] = arg.slice(2).split(\"=\", 2);\n if (flag.length === 0) {\n throw new Error(\"Encountered an empty option flag.\");\n }\n\n const nextValue = inlineValue ?? argv[index + 1];\n switch (flag) {\n case \"check\":\n options.auditCheck = true;\n break;\n case \"config\":\n options.config = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"catalog\":\n (options.catalogIds ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"dry-run\":\n options.dryRun = true;\n break;\n case \"force\":\n options.force = true;\n break;\n case \"force-retranslate\":\n options.forceRetranslate = true;\n break;\n case \"force-retranslate-path\":\n (options.forceRetranslatePaths ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"from\":\n options.from = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"include-path\":\n (options.includePaths ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"integration\":\n options.integration = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"locale\":\n (options.locales ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"model\":\n options.model = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"preview\":\n options.preview = true;\n break;\n case \"provider\":\n options.provider = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"provider-package\":\n options.providerPackage = requireOptionValue(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"max-pending-translations\":\n options.maxPendingTranslations = requireNonNegativeIntegerOption(flag, nextValue);\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"identical-to-source\":\n options.identicalToSource = requireIdenticalToSourcePolicy(\n requireOptionValue(flag, nextValue),\n );\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n case \"refresh\":\n options.refresh = true;\n break;\n case \"strategy\": {\n const strategy = requireOptionValue(flag, nextValue) as CatalogScaffoldStrategy;\n options.strategy = strategy;\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n }\n case \"unit\":\n (options.unitIds ??= []).push(requireOptionValue(flag, nextValue));\n if (inlineValue === undefined) {\n index += 1;\n }\n break;\n default:\n throw new Error(`Unknown option \"--${flag}\".`);\n }\n\n continue;\n }\n\n if (!command) {\n command = arg;\n continue;\n }\n\n positionals.push(arg);\n }\n\n const parsedCommand: ParsedCommand = {\n options,\n positionals,\n };\n if (command !== undefined) {\n parsedCommand.command = command;\n }\n\n return parsedCommand;\n}\n\nexport async function runCli(\n argv: readonly string[] = process.argv.slice(2),\n cwd: string = process.cwd(),\n): Promise<number> {\n try {\n const parsed = parseCommand(argv);\n if (!parsed.command || parsed.command === \"help\") {\n printHelp();\n return 0;\n }\n\n if (parsed.command === \"version\") {\n console.log(\"0.0.0\");\n return 0;\n }\n\n switch (parsed.command) {\n case \"init\": {\n // No loadConfig and no loadEnvFiles: init runs before either exists.\n const result = await runInit(cwd, {\n force: parsed.options.force === true,\n ...(parsed.options.integration === undefined\n ? {}\n : { integration: parsed.options.integration }),\n ...(parsed.options.model === undefined ? {} : { model: parsed.options.model }),\n preview: parsed.options.preview === true || parsed.options.dryRun === true,\n ...(parsed.options.provider === undefined\n ? {}\n : { provider: requireProviderChoice(parsed.options.provider) }),\n ...(parsed.options.providerPackage === undefined\n ? {}\n : { providerPackage: parsed.options.providerPackage }),\n });\n console.log(result.lines.join(\"\\n\"));\n return 0;\n }\n case \"validate\": {\n await loadEnvFiles(cwd);\n const { config, configPath } = await loadConfig(cwd, parsed.options.config);\n const summary = await validateConfig(config, configPath, buildSyncOptions(parsed.options));\n console.log(JSON.stringify(summary, null, 2));\n if (summary.issues.some((issue) => issue.severity === \"error\")) {\n throw new Error(\"Validation failed.\");\n }\n return 0;\n }\n case \"check\": {\n await loadEnvFiles(cwd);\n const { config, configPath } = await loadConfig(cwd, parsed.options.config);\n const checkOptions: SyncCatalogsOptions = {\n ...buildSyncOptions(parsed.options),\n ...(process.env.AI_TRANSLATE_CHECK_SNAPSHOT_LOCK === \"1\"\n ? { assumeStateLock: true }\n : {}),\n };\n // Ask the store to materialise only the locales under check, then keep\n // the projection: a store is free to ignore the scope and return a\n // superset, and check must narrow regardless of which store is wired up.\n const stateSnapshot = projectStateLocales(\n await config.state.load(\n checkOptions.locales === undefined ? undefined : { locales: checkOptions.locales },\n ),\n checkOptions.locales,\n );\n const checkConfig: AiTranslateConfig = {\n ...config,\n state: {\n load: () => Promise.resolve(stateSnapshot),\n save: () =>\n Promise.reject(new Error(\"Translation check cannot persist translation state.\")),\n withLock: (operation) => config.state.withLock(operation),\n },\n };\n const needsSemanticAudit =\n (checkConfig.semanticAudits?.length ?? 0) > 0 || hasStoredSemanticAudits(stateSnapshot);\n const { auditResult, dryRunResult, validationResult } = await withTranslationIssueCache(\n async () => {\n const checkedValidation = await validateConfig(checkConfig, configPath, {\n ...checkOptions,\n acceptedProvenanceFastPath: true,\n });\n const checkedDryRun = await syncCatalogs(checkConfig, {\n ...checkOptions,\n dryRun: true,\n });\n const checkedAudit = needsSemanticAudit\n ? await auditCatalogs(checkConfig, {\n ...checkOptions,\n checkOnly: true,\n })\n : EMPTY_SEMANTIC_AUDIT;\n return {\n auditResult: checkedAudit,\n dryRunResult: checkedDryRun,\n validationResult: checkedValidation,\n };\n },\n );\n const hasValidationErrors = validationResult.issues.some(\n (issue) => issue.severity === \"error\",\n );\n const hasPendingSync =\n dryRunResult.metrics.changedDocuments > 0 ||\n dryRunResult.metrics.failedEntries > 0 ||\n dryRunResult.metrics.staleManualEntries > 0 ||\n dryRunResult.metrics.translatedEntries > 0;\n const hasAuditErrors = auditResult.issues.some((issue) => issue.severity === \"error\");\n\n console.log(\n JSON.stringify(\n {\n validation: validationResult,\n audit: auditResult,\n dryRun: dryRunResult.metrics,\n },\n null,\n 2,\n ),\n );\n if (hasValidationErrors || hasPendingSync || hasAuditErrors) {\n if (hasAuditErrors && !hasValidationErrors && !hasPendingSync) {\n throw new Error(\n \"Translation check failed because semantic audit provenance is missing, stale, or unresolved. Run ai-translate audit --refresh.\",\n );\n }\n throw new Error(\n \"Translation check failed. Run ai-translate sync to reconcile localized content.\",\n );\n }\n return 0;\n }\n case \"audit\": {\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const result = await auditCatalogs(config, {\n ...buildSyncOptions(parsed.options),\n checkOnly: parsed.options.auditCheck ?? false,\n refresh: parsed.options.refresh ?? false,\n });\n console.log(JSON.stringify(result, null, 2));\n if (result.issues.some((issue) => issue.severity === \"error\")) {\n throw new Error(\n parsed.options.auditCheck\n ? \"Semantic audit check failed. Run ai-translate audit --refresh.\"\n : \"Semantic audit completed with unresolved or unsafe translations.\",\n );\n }\n return 0;\n }\n case \"sync\": {\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n /*\n * The cache key is the full validation input, so a changed translation\n * gets a fresh entry. Sync validates the same entry once to decide\n * whether existing output is still valid and again while resolving\n * acceptance provenance; `check` has always deduplicated that pair.\n */\n const result = await withTranslationIssueCache(() =>\n syncWithSemanticAuditConvergence(config, buildSyncOptions(parsed.options)),\n );\n printSyncSummary(result.sync, result.audit, result.repairRounds);\n assertDryRunBudget(config, result.sync);\n assertSemanticAuditConvergence(result);\n return 0;\n }\n case \"new-locale\": {\n const locale = parsed.positionals[0];\n if (!locale) {\n throw new Error('The \"new-locale\" command requires a <locale> argument.');\n }\n\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const fromLocale = parsed.options.from ?? config.sourceLocale;\n const strategy = parsed.options.strategy ?? \"copy-source\";\n\n if (parsed.options.dryRun && fromLocale !== config.sourceLocale) {\n throw new Error(\n 'The \"new-locale\" command only supports --from <sourceLocale> when used with --dry-run.',\n );\n }\n\n if (parsed.options.dryRun && strategy !== \"copy-source\") {\n throw new Error(\n 'The \"new-locale\" command only supports --strategy copy-source when used with --dry-run.',\n );\n }\n\n if (strategy !== \"copy-source\" && fromLocale === config.sourceLocale) {\n throw new Error(\n `The \"${strategy}\" strategy requires --from <locale> to be a translated locale.`,\n );\n }\n\n const syncOptions: SyncCatalogsOptions = {\n ...buildSyncOptions(parsed.options),\n forceRetranslate: strategy === \"copy-locale-and-retranslate\",\n locales: [locale],\n };\n const transaction = parsed.options.dryRun\n ? {\n result: await convergeSemanticAudits(config, syncOptions),\n scaffoldResults: [],\n }\n : await runStagedCatalogTransaction(\n config,\n async (stagedConfig) => {\n const scaffoldResults = await scaffoldLocale(stagedConfig, locale, {\n fromLocale,\n strategy,\n });\n const result = await convergeSemanticAudits(stagedConfig, syncOptions);\n return { result, scaffoldResults };\n },\n ({ result }) => semanticAuditConvergenceError(result) === undefined,\n );\n const { result, scaffoldResults } = transaction;\n console.log(\n JSON.stringify(\n {\n dryRun: result.sync.dryRun,\n fromLocale,\n locale,\n metrics: result.sync.metrics,\n scaffoldResults,\n ...(result.audit === undefined\n ? {}\n : {\n semanticAudit: result.audit,\n semanticRepairRounds: result.repairRounds,\n }),\n strategy,\n status: semanticAuditConvergenceError(result) === undefined ? \"ok\" : \"failed\",\n },\n null,\n 2,\n ),\n );\n assertSemanticAuditConvergence(result);\n return 0;\n }\n case \"scaffold-locale\": {\n const locale = parsed.positionals[0];\n if (!locale) {\n throw new Error('The \"scaffold-locale\" command requires a <locale> argument.');\n }\n\n if (!parsed.options.from) {\n throw new Error('The \"scaffold-locale\" command requires --from <locale>.');\n }\n\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const scaffoldResults = await scaffoldLocale(config, locale, {\n fromLocale: parsed.options.from,\n strategy: parsed.options.strategy ?? \"copy-locale\",\n });\n console.log(\n JSON.stringify(\n {\n fromLocale: parsed.options.from,\n locale,\n scaffoldResults,\n strategy: parsed.options.strategy ?? \"copy-locale\",\n status: \"ok\",\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n case \"adopt\": {\n await loadEnvFiles(cwd);\n const { config } = await loadConfig(cwd, parsed.options.config);\n const result = await adoptExistingTranslations({\n catalogs: config.catalogs,\n identicalToSource: parsed.options.identicalToSource ?? \"adopt\",\n sourceLocale: config.sourceLocale,\n targetLocales: config.targetLocales,\n });\n\n if (!parsed.options.dryRun) {\n await config.state.save(result.state);\n }\n\n console.log(\n JSON.stringify(\n {\n adopted: result.adopted,\n dryRun: parsed.options.dryRun === true,\n identicalToSource: result.identicalToSource,\n status: \"ok\",\n untranslated: result.untranslated,\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n default:\n throw new Error(`Unknown command \"${parsed.command}\".`);\n }\n } catch (error) {\n console.error(\n error instanceof Error ? error.message : `Unexpected CLI failure: ${String(error)}`,\n );\n return 1;\n }\n}\n"],"mappings":"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"}